diff -ur v2.6.9/linux/Documentation/filesystems/proc.txt linux/Documentation/filesystems/proc.txt
--- v2.6.9/linux/Documentation/filesystems/proc.txt	2004-09-25 08:01:24.000000000 +0300
+++ linux/Documentation/filesystems/proc.txt	2004-09-25 14:37:37.775397048 +0300
@@ -1649,6 +1649,16 @@
 (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 -ur v2.6.9/linux/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt
--- v2.6.9/linux/Documentation/networking/ip-sysctl.txt	2004-09-25 08:01:24.000000000 +0300
+++ linux/Documentation/networking/ip-sysctl.txt	2004-09-25 14:37:37.776396896 +0300
@@ -542,6 +542,15 @@
 	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 -ur v2.6.9/linux/include/linux/inetdevice.h linux/include/linux/inetdevice.h
--- v2.6.9/linux/include/linux/inetdevice.h	2004-09-25 08:01:25.000000000 +0300
+++ linux/include/linux/inetdevice.h	2004-09-25 14:37:37.777396744 +0300
@@ -26,6 +26,7 @@
 	int	no_xfrm;
 	int	no_policy;
 	int	force_igmp_version;
+	int	rp_filter_mask;
 	void	*sysctl;
 };
 
@@ -68,6 +69,7 @@
 #define IN_DEV_SEC_REDIRECTS(in_dev)	(ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects)
 #define IN_DEV_IDTAG(in_dev)		((in_dev)->cnf.tag)
 #define IN_DEV_MEDIUM_ID(in_dev)	((in_dev)->cnf.medium_id)
+#define IN_DEV_RPFILTER_MASK(in_dev)	((in_dev)->cnf.rp_filter_mask)
 
 #define IN_DEV_RX_REDIRECTS(in_dev) \
 	((IN_DEV_FORWARD(in_dev) && \
diff -ur v2.6.9/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.6.9/linux/include/linux/sysctl.h	2004-09-25 08:01:26.000000000 +0300
+++ linux/include/linux/sysctl.h	2004-09-25 14:37:37.778396592 +0300
@@ -393,6 +393,7 @@
 	NET_IPV4_CONF_FORCE_IGMP_VERSION=17,
 	NET_IPV4_CONF_ARP_ANNOUNCE=18,
 	NET_IPV4_CONF_ARP_IGNORE=19,
+	NET_IPV4_CONF_RP_FILTER_MASK=20,
 };
 
 /* /proc/sys/net/ipv4/netfilter */
diff -ur v2.6.9/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v2.6.9/linux/net/ipv4/devinet.c	2004-09-25 08:01:26.000000000 +0300
+++ linux/net/ipv4/devinet.c	2004-09-25 14:37:37.779396440 +0300
@@ -1213,7 +1213,7 @@
 
 static struct devinet_sysctl_table {
 	struct ctl_table_header *sysctl_header;
-	ctl_table		devinet_vars[20];
+	ctl_table		devinet_vars[21];
 	ctl_table		devinet_dev[2];
 	ctl_table		devinet_conf_dir[2];
 	ctl_table		devinet_proto_dir[2];
@@ -1301,6 +1301,14 @@
 			.proc_handler	= &proc_dointvec,
 		},
 		{
+			.ctl_name	= NET_IPV4_CONF_RP_FILTER_MASK,
+			.procname	= "rp_filter_mask",
+			.data		= &ipv4_devconf.rp_filter_mask,
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= &proc_dointvec,
+		},
+		{
 			.ctl_name	= NET_IPV4_CONF_BOOTP_RELAY,
 			.procname	= "bootp_relay",
 			.data		= &ipv4_devconf.bootp_relay,
diff -ur v2.6.9/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- v2.6.9/linux/net/ipv4/fib_frontend.c	2004-09-25 13:58:00.000000000 +0300
+++ linux/net/ipv4/fib_frontend.c	2004-09-25 14:39:21.859573848 +0300
@@ -169,6 +169,7 @@
 			    .iif = oif };
 	struct fib_result res;
 	int no_addr, rpf;
+	unsigned rpf_mask = 0;
 	int ret;
 
 	no_addr = rpf = 0;
@@ -177,6 +178,7 @@
 	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();
 
@@ -199,6 +201,17 @@
 		fib_res_put(&res);
 		return ret;
 	}
+	if (rpf_mask && rpf) {
+		int omi = 0;
+
+		rcu_read_lock();
+		in_dev = __in_dev_get(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;
