diff -urp v6.13/linux/Documentation/networking/ip-sysctl.rst linux/Documentation/networking/ip-sysctl.rst
--- v6.13/linux/Documentation/networking/ip-sysctl.rst	2025-02-02 09:44:49.000000000 +0200
+++ linux/Documentation/networking/ip-sysctl.rst	2025-02-02 14:32:32.831213673 +0200
@@ -1623,6 +1623,19 @@ forwarding - BOOLEAN
 	Enable IP forwarding on this interface.  This controls whether packets
 	received _on_ this interface can be forwarded.
 
+forward_shared - BOOLEAN
+	Integer value determines if a source validation should allow
+	forwarding of packets with local source address. 1 means yes,
+	0 means no. By default the flag is disabled and such packets
+	are not forwarded.
+ 
+	If you enable this flag on internal network, the router will forward
+	packets from internal hosts with shared IP addresses no matter how
+	the rp_filter is set. This flag is activated only if it is
+	enabled both in specific device section and in "all" section.
+
+	The forward_shared value could be ignored when rp_filter is set to 0.
+
 mc_forwarding - BOOLEAN
 	Do multicast routing. The kernel needs to be compiled with CONFIG_MROUTE
 	and a multicast routing daemon is required.
diff -urp v6.13/linux/include/linux/inetdevice.h linux/include/linux/inetdevice.h
--- v6.13/linux/include/linux/inetdevice.h	2025-02-02 09:44:49.000000000 +0200
+++ linux/include/linux/inetdevice.h	2025-02-02 14:32:32.832213661 +0200
@@ -104,6 +104,7 @@ static inline void ipv4_devconf_setall(s
 #define IN_DEV_SRC_VMARK(in_dev)    	IN_DEV_ORCONF((in_dev), SRC_VMARK)
 #define IN_DEV_SOURCE_ROUTE(in_dev)	IN_DEV_ANDCONF((in_dev), \
 						       ACCEPT_SOURCE_ROUTE)
+#define IN_DEV_FORWARD_SHARED(in_dev)	IN_DEV_ANDCONF((in_dev), FORWARD_SHARED)
 #define IN_DEV_ACCEPT_LOCAL(in_dev)	IN_DEV_ORCONF((in_dev), ACCEPT_LOCAL)
 #define IN_DEV_BOOTP_RELAY(in_dev)	IN_DEV_ANDCONF((in_dev), BOOTP_RELAY)
 
diff -urp v6.13/linux/include/net/ip_fib.h linux/include/net/ip_fib.h
--- v6.13/linux/include/net/ip_fib.h	2025-02-02 07:49:05.000000000 +0200
+++ linux/include/net/ip_fib.h	2025-02-02 14:43:48.179731715 +0200
@@ -450,15 +450,15 @@ __be32 fib_compute_spec_dst(struct sk_bu
 bool fib_info_nh_uses_dev(struct fib_info *fi, const struct net_device *dev);
 int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 			dscp_t dscp, int oif, struct net_device *dev,
-			struct in_device *idev, u32 *itag);
+			struct in_device *idev, u32 *itag, int our);
 
 static inline enum skb_drop_reason
 fib_validate_source_reason(struct sk_buff *skb, __be32 src, __be32 dst,
 			   dscp_t dscp, int oif, struct net_device *dev,
-			   struct in_device *idev, u32 *itag)
+			   struct in_device *idev, u32 *itag, int our)
 {
 	int err = fib_validate_source(skb, src, dst, dscp, oif, dev, idev,
-				      itag);
+				      itag, our);
 	if (err < 0)
 		return -err;
 	return SKB_NOT_DROPPED_YET;
diff -urp v6.13/linux/include/uapi/linux/ip.h linux/include/uapi/linux/ip.h
--- v6.13/linux/include/uapi/linux/ip.h	2025-02-02 09:44:49.000000000 +0200
+++ linux/include/uapi/linux/ip.h	2025-02-02 14:32:32.834213636 +0200
@@ -173,6 +173,7 @@ enum
 	IPV4_DEVCONF_DROP_GRATUITOUS_ARP,
 	IPV4_DEVCONF_BC_FORWARDING,
 	IPV4_DEVCONF_ARP_EVICT_NOCARRIER,
+	IPV4_DEVCONF_FORWARD_SHARED,
 	__IPV4_DEVCONF_MAX
 };
 
diff -urp v6.13/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v6.13/linux/net/ipv4/devinet.c	2025-02-02 09:44:49.000000000 +0200
+++ linux/net/ipv4/devinet.c	2025-02-02 14:32:32.835213623 +0200
@@ -2571,6 +2571,7 @@ static struct devinet_sysctl_table {
 		DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"),
 		DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE,
 					"accept_source_route"),
+		DEVINET_SYSCTL_RW_ENTRY(FORWARD_SHARED, "forward_shared"),
 		DEVINET_SYSCTL_RW_ENTRY(ACCEPT_LOCAL, "accept_local"),
 		DEVINET_SYSCTL_RW_ENTRY(SRC_VMARK, "src_valid_mark"),
 		DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"),
diff -urp v6.13/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- v6.13/linux/net/ipv4/fib_frontend.c	2025-02-02 07:49:05.000000000 +0200
+++ linux/net/ipv4/fib_frontend.c	2025-02-02 14:38:19.591858572 +0200
@@ -343,7 +343,8 @@ EXPORT_SYMBOL_GPL(fib_info_nh_uses_dev);
  */
 static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 				 dscp_t dscp, int oif, struct net_device *dev,
-				 int rpf, struct in_device *idev, u32 *itag)
+				 int rpf, struct in_device *idev, u32 *itag,
+				 int our)
 {
 	struct net *net = dev_net(dev);
 	enum skb_drop_reason reason;
@@ -351,6 +352,7 @@ static int __fib_validate_source(struct
 	int ret, no_addr;
 	struct fib_result res;
 	struct flowi4 fl4;
+	int fwdsh;
 	bool dev_match;
 
 	fl4.flowi4_oif = 0;
@@ -367,6 +369,7 @@ static int __fib_validate_source(struct
 
 	no_addr = idev->ifa_list == NULL;
 
+	fwdsh = IN_DEV_FORWARD_SHARED(idev);
 	fl4.flowi4_mark = IN_DEV_SRC_VMARK(idev) ? skb->mark : 0;
 	if (!fib4_rules_early_flow_dissect(net, skb, &fl4, &flkeys)) {
 		fl4.flowi4_proto = 0;
@@ -378,7 +381,12 @@ static int __fib_validate_source(struct
 
 	if (fib_lookup(net, &fl4, &res, 0))
 		goto last_resort;
-	if (res.type != RTN_UNICAST) {
+	if (fwdsh) {
+		fwdsh = (res.type == RTN_LOCAL && !our);
+		if (fwdsh)
+			rpf = 0;
+	}
+	if (res.type != RTN_UNICAST && !fwdsh) {
 		if (res.type != RTN_LOCAL) {
 			reason = SKB_DROP_REASON_IP_INVALID_SOURCE;
 			goto e_inval;
@@ -404,6 +412,8 @@ static int __fib_validate_source(struct
 	if (rpf == 1)
 		goto e_rpf;
 	fl4.flowi4_oif = dev->ifindex;
+	if (fwdsh)
+		fl4.flowi4_iif = LOOPBACK_IFINDEX;
 
 	ret = 0;
 	if (fib_lookup(net, &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE) == 0) {
@@ -427,7 +437,7 @@ e_rpf:
 /* Ignore rp_filter for packets protected by IPsec. */
 int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 			dscp_t dscp, int oif, struct net_device *dev,
-			struct in_device *idev, u32 *itag)
+			struct in_device *idev, u32 *itag, int our)
 {
 	int r = secpath_exists(skb) ? 0 : IN_DEV_RPFILTER(idev);
 	struct net *net = dev_net(dev);
@@ -456,7 +466,7 @@ ok:
 
 full_check:
 	return __fib_validate_source(skb, src, dst, dscp, oif, dev, r, idev,
-				     itag);
+				     itag, our);
 }
 
 static inline __be32 sk_extract_addr(struct sockaddr *addr)
diff -urp v6.13/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v6.13/linux/net/ipv4/route.c	2025-02-02 07:49:05.000000000 +0200
+++ linux/net/ipv4/route.c	2025-02-02 14:43:15.024148125 +0200
@@ -1704,7 +1704,7 @@ ip_mc_validate_source(struct sk_buff *sk
 			return SKB_DROP_REASON_IP_INVALID_SOURCE;
 	} else {
 		reason = fib_validate_source_reason(skb, saddr, 0, dscp, 0,
-						    dev, in_dev, itag);
+						    dev, in_dev, itag, 1);
 		if (reason)
 			return reason;
 	}
@@ -1805,7 +1805,7 @@ __mkroute_input(struct sk_buff *skb, con
 	}
 
 	err = fib_validate_source(skb, saddr, daddr, dscp, FIB_RES_OIF(*res),
-				  in_dev->dev, in_dev, &itag);
+				  in_dev->dev, in_dev, &itag, 0);
 	if (err < 0) {
 		reason = -err;
 		ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr,
@@ -2187,7 +2187,7 @@ ip_route_use_hint(struct sk_buff *skb, _
 		goto skip_validate_source;
 
 	reason = fib_validate_source_reason(skb, saddr, daddr, dscp, 0, dev,
-					    in_dev, &tag);
+					    in_dev, &tag, 0);
 	if (reason)
 		goto martian_source;
 
@@ -2339,7 +2339,7 @@ ip_route_input_slow(struct sk_buff *skb,
 	err = -EINVAL;
 	if (res->type == RTN_LOCAL) {
 		reason = fib_validate_source_reason(skb, saddr, daddr, dscp,
-						    0, dev, in_dev, &itag);
+						    0, dev, in_dev, &itag, 1);
 		if (reason)
 			goto martian_source;
 		goto local_input;
@@ -2369,7 +2369,7 @@ brd_input:
 
 	if (!ipv4_is_zeronet(saddr)) {
 		reason = fib_validate_source_reason(skb, saddr, 0, dscp, 0,
-						    dev, in_dev, &itag);
+						    dev, in_dev, &itag, 1);
 		if (reason)
 			goto martian_source;
 	}
