diff -urp v2.6.24/linux/Documentation/filesystems/proc.txt linux/Documentation/filesystems/proc.txt
--- v2.6.24/linux/Documentation/filesystems/proc.txt	2008-01-25 10:44:55.000000000 +0200
+++ linux/Documentation/filesystems/proc.txt	2008-02-05 01:11:47.000000000 +0200
@@ -1826,6 +1826,16 @@ the net,  it  will  prevent  spoofing  a
 (external addresses  can  still  be  spoofed), without the need for additional
 firewall rules.
 
+rp_filter_mask
+--------------
+
+Integer  value representing bitmask of the  mediums for which the reverse path
+protection  is disabled. If  the source validation results  in reverse path to
+interface with medium_id value in the 1..31 range the access is allowed if the
+corresponding  bit is set in the bitmask. The bitmask value is considered only
+when  rp_filter is  enabled. By  default the  bitmask is  empty preserving the
+original rp_filter semantic.
+
 secure_redirects
 ----------------
 
diff -urp v2.6.24/linux/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt
--- v2.6.24/linux/Documentation/networking/ip-sysctl.txt	2008-01-25 10:44:55.000000000 +0200
+++ linux/Documentation/networking/ip-sysctl.txt	2008-02-05 01:11:48.000000000 +0200
@@ -677,6 +677,15 @@ rp_filter - BOOLEAN
 	Default value is 0. Note that some distributions enable it
 	in startup scripts.
 
+rp_filter_mask - INTEGER
+	Integer value representing bitmask of the mediums for which the
+	reverse path protection is disabled. If the source validation
+	results in reverse path to interface with medium_id value in
+	the 1..31 range the access is allowed if the corresponding bit
+	is set in the bitmask. The bitmask value is considered only when
+	rp_filter is enabled. By default the bitmask is empty preserving
+	the original rp_filter semantic.
+
 arp_filter - BOOLEAN
 	1 - Allows you to have multiple network interfaces on the same
 	subnet, and have the ARPs for each interface be answered
diff -urp v2.6.24/linux/include/linux/inetdevice.h linux/include/linux/inetdevice.h
--- v2.6.24/linux/include/linux/inetdevice.h	2007-07-10 09:18:42.000000000 +0300
+++ linux/include/linux/inetdevice.h	2008-02-05 01:11:48.000000000 +0200
@@ -97,6 +97,7 @@ static inline void ipv4_devconf_setall(s
 #define IN_DEV_PROMOTE_SECONDARIES(in_dev) \
 					IN_DEV_ORCONF((in_dev), \
 						      PROMOTE_SECONDARIES)
+#define IN_DEV_RPFILTER_MASK(in_dev)	IN_DEV_CONF_GET(in_dev, RP_FILTER_MASK)
 
 #define IN_DEV_RX_REDIRECTS(in_dev) \
 	((IN_DEV_FORWARD(in_dev) && \
diff -urp v2.6.24/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.6.24/linux/include/linux/sysctl.h	2008-01-25 10:45:05.000000000 +0200
+++ linux/include/linux/sysctl.h	2008-02-05 01:11:48.000000000 +0200
@@ -491,6 +491,7 @@ enum
 	NET_IPV4_CONF_ARP_IGNORE=19,
 	NET_IPV4_CONF_PROMOTE_SECONDARIES=20,
 	NET_IPV4_CONF_ARP_ACCEPT=21,
+	NET_IPV4_CONF_RP_FILTER_MASK=22,
 	__NET_IPV4_CONF_MAX
 };
 
diff -urp v2.6.24/linux/kernel/sysctl_check.c linux/kernel/sysctl_check.c
--- v2.6.24/linux/kernel/sysctl_check.c	2008-01-25 10:45:06.000000000 +0200
+++ linux/kernel/sysctl_check.c	2008-02-05 01:13:21.000000000 +0200
@@ -224,6 +224,7 @@ static struct trans_ctl_table trans_net_
 	{ NET_IPV4_CONF_ARP_IGNORE,		"arp_ignore" },
 	{ NET_IPV4_CONF_PROMOTE_SECONDARIES,	"promote_secondaries" },
 	{ NET_IPV4_CONF_ARP_ACCEPT,		"arp_accept" },
+	{ NET_IPV4_CONF_RP_FILTER_MASK,		"rp_filter_mask" },
 	{}
 };
 
diff -urp v2.6.24/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v2.6.24/linux/net/ipv4/devinet.c	2008-01-25 10:45:06.000000000 +0200
+++ linux/net/ipv4/devinet.c	2008-02-05 01:11:48.000000000 +0200
@@ -1440,6 +1440,7 @@ static struct devinet_sysctl_table {
 					"accept_source_route"),
 		DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"),
 		DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"),
+		DEVINET_SYSCTL_RW_ENTRY(RP_FILTER_MASK, "rp_filter_mask"),
 		DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"),
 		DEVINET_SYSCTL_RW_ENTRY(LOG_MARTIANS, "log_martians"),
 		DEVINET_SYSCTL_RW_ENTRY(TAG, "tag"),
diff -urp v2.6.24/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- v2.6.24/linux/net/ipv4/fib_frontend.c	2008-01-25 10:45:06.000000000 +0200
+++ linux/net/ipv4/fib_frontend.c	2008-02-05 01:11:48.000000000 +0200
@@ -201,6 +201,7 @@ int fib_validate_source(__be32 src, __be
 			    .iif = oif };
 	struct fib_result res;
 	int no_addr, rpf;
+	unsigned rpf_mask = 0;
 	int ret;
 
 	no_addr = rpf = 0;
@@ -209,6 +210,7 @@ int fib_validate_source(__be32 src, __be
 	if (in_dev) {
 		no_addr = in_dev->ifa_list == NULL;
 		rpf = IN_DEV_RPFILTER(in_dev);
+		rpf_mask = IN_DEV_RPFILTER_MASK(in_dev);
 	}
 	rcu_read_unlock();
 
@@ -231,6 +233,17 @@ int fib_validate_source(__be32 src, __be
 		fib_res_put(&res);
 		return ret;
 	}
+	if (rpf_mask && rpf) {
+		int omi = 0;
+
+		rcu_read_lock();
+		in_dev = __in_dev_get_rcu(FIB_RES_DEV(res));
+		if (in_dev)
+			omi = IN_DEV_MEDIUM_ID(in_dev);
+		rcu_read_unlock();
+		if (omi >= 1 && omi <= 31 && ((1 << omi) & rpf_mask))
+			rpf = 0;
+	}
 	fib_res_put(&res);
 	if (no_addr)
 		goto last_resort;
