diff -ur v2.6.12/linux/Documentation/filesystems/proc.txt linux/Documentation/filesystems/proc.txt
--- v2.6.12/linux/Documentation/filesystems/proc.txt	2005-06-18 08:50:48.000000000 +0300
+++ linux/Documentation/filesystems/proc.txt	2005-06-18 09:56:39.551065752 +0300
@@ -1659,6 +1659,18 @@
 (external addresses  can  still  be  spoofed), without the need for additional
 firewall rules.
 
+forward_shared
+--------------
+
+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.
+
 secure_redirects
 ----------------
 
@@ -1676,6 +1688,16 @@
 
 Determines whether to send ICMP redirects to other hosts.
 
+hidden
+------
+
+Hide  addresses attached  to this device  from other  devices.  Such addresses
+will  never be selected  by source address  autoselection mechanism, host does
+not  answer broadcast ARP requests for them,  does not announce them as source
+address  of ARP requests,  but they are  still reachable via  IP. This flag is
+activated  only if it is enabled both  in specific device section and in "all"
+section.
+
 Routing settings
 ----------------
 
diff -ur v2.6.12/linux/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt
--- v2.6.12/linux/Documentation/networking/ip-sysctl.txt	2004-12-25 11:49:49.000000000 +0200
+++ linux/Documentation/networking/ip-sysctl.txt	2005-06-18 10:02:39.110404424 +0300
@@ -471,6 +471,17 @@
 forwarding - BOOLEAN
 	Enable IP forwarding on this interface.
 
+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.
+
 mc_forwarding - BOOLEAN
 	Do multicast routing. The kernel needs to be compiled with CONFIG_MROUTE
 	and a multicast routing daemon is required.
@@ -627,12 +638,20 @@
 disable_xfrm - BOOLEAN
 	Disable IPSEC encryption on this interface, whatever the policy
 
+hidden - BOOLEAN
+	Hide addresses attached to this device from other devices.
+	Such addresses will never be selected by source address autoselection
+	mechanism, host does not answer broadcast ARP requests for them,
+	does not announce them as source address of ARP requests, but they
+	are still reachable via IP. This flag is activated only if it is
+	enabled both in specific device section and in "all" section.
 
 
 tag - INTEGER
 	Allows you to write a number, which can be used as required.
 	Default value is 0.
 
+ 
 (1) Jiffie: internal timeunit for the kernel. On the i386 1/100s, on the
 Alpha 1/1024s. See the HZ define in /usr/include/asm/param.h for the exact
 value on your system. 
diff -ur v2.6.12/linux/include/linux/inetdevice.h linux/include/linux/inetdevice.h
--- v2.6.12/linux/include/linux/inetdevice.h	2005-06-18 08:50:52.000000000 +0300
+++ linux/include/linux/inetdevice.h	2005-06-18 09:57:35.692530952 +0300
@@ -30,6 +30,8 @@
 	int	no_policy;
 	int	force_igmp_version;
 	int	promote_secondaries;
+	int	hidden;
+	int	forward_shared;
 	void	*sysctl;
 };
 
@@ -67,6 +69,7 @@
 
 #define IN_DEV_LOG_MARTIANS(in_dev)	(ipv4_devconf.log_martians || (in_dev)->cnf.log_martians)
 #define IN_DEV_PROXY_ARP(in_dev)	(ipv4_devconf.proxy_arp || (in_dev)->cnf.proxy_arp)
+#define IN_DEV_HIDDEN(in_dev)		((in_dev)->cnf.hidden && ipv4_devconf.hidden)
 #define IN_DEV_SHARED_MEDIA(in_dev)	(ipv4_devconf.shared_media || (in_dev)->cnf.shared_media)
 #define IN_DEV_TX_REDIRECTS(in_dev)	(ipv4_devconf.send_redirects || (in_dev)->cnf.send_redirects)
 #define IN_DEV_SEC_REDIRECTS(in_dev)	(ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects)
@@ -84,6 +87,8 @@
 #define IN_DEV_ARP_ANNOUNCE(in_dev)	(max(ipv4_devconf.arp_announce, (in_dev)->cnf.arp_announce))
 #define IN_DEV_ARP_IGNORE(in_dev)	(max(ipv4_devconf.arp_ignore, (in_dev)->cnf.arp_ignore))
 
+#define IN_DEV_FORWARD_SHARED(in_dev)	((in_dev)->cnf.forward_shared && ipv4_devconf.forward_shared)
+
 struct in_ifaddr
 {
 	struct in_ifaddr	*ifa_next;
diff -ur v2.6.12/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.6.12/linux/include/linux/sysctl.h	2005-06-18 08:50:52.000000000 +0300
+++ linux/include/linux/sysctl.h	2005-06-18 09:58:12.888876248 +0300
@@ -401,6 +401,8 @@
 	NET_IPV4_CONF_ARP_ANNOUNCE=18,
 	NET_IPV4_CONF_ARP_IGNORE=19,
 	NET_IPV4_CONF_PROMOTE_SECONDARIES=20,
+	NET_IPV4_CONF_HIDDEN=21,
+	NET_IPV4_CONF_FORWARD_SHARED=22,
 	__NET_IPV4_CONF_MAX
 };
 
diff -ur v2.6.12/linux/include/net/ip_fib.h linux/include/net/ip_fib.h
--- v2.6.12/linux/include/net/ip_fib.h	2005-06-18 08:50:52.000000000 +0300
+++ linux/include/net/ip_fib.h	2005-06-18 09:56:39.554065296 +0300
@@ -221,7 +221,7 @@
 extern int inet_rtm_getroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
 extern int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb);
 extern int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
-			       struct net_device *dev, u32 *spec_dst, u32 *itag);
+			       struct net_device *dev, u32 *spec_dst, u32 *itag, int our);
 extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res);
 
 /* Exported by fib_semantics.c */
diff -ur v2.6.12/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.6.12/linux/net/ipv4/arp.c	2005-06-18 08:50:52.000000000 +0300
+++ linux/net/ipv4/arp.c	2005-06-18 09:56:39.555065144 +0300
@@ -72,6 +72,8 @@
  *					bonding can change the skb before
  *					sending (e.g. insert 8021q tag).
  *		Harald Welte	:	convert to make use of jenkins hash
+ *		Julian Anastasov:	"hidden" flag: hide the
+ *					interface and don't reply for it
  */
 
 #include <linux/module.h>
@@ -335,21 +337,34 @@
 	u32 target = *(u32*)neigh->primary_key;
 	int probes = atomic_read(&neigh->probes);
 	struct in_device *in_dev = in_dev_get(dev);
+	struct in_device *in_dev2 = NULL;
+	struct net_device *dev2 = NULL;
+	int mode;
 
 	if (!in_dev)
 		return;
 
-	switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
+	mode = IN_DEV_ARP_ANNOUNCE(in_dev);
+	if (mode != 2 && skb && (dev2 = ip_dev_find(skb->nh.iph->saddr)) != NULL &&
+	    (saddr = skb->nh.iph->saddr, in_dev2 = in_dev_get(dev2)) != NULL &&
+	    IN_DEV_HIDDEN(in_dev2)) {
+		saddr = 0;
+		goto get;
+	}
+
+	switch (mode) {
 	default:
 	case 0:		/* By default announce any local IP */
+		if (saddr)
+			break;
 		if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL)
 			saddr = skb->nh.iph->saddr;
 		break;
 	case 1:		/* Restrict announcements of saddr in same subnet */
 		if (!skb)
 			break;
-		saddr = skb->nh.iph->saddr;
-		if (inet_addr_type(saddr) == RTN_LOCAL) {
+		if (saddr || (saddr = skb->nh.iph->saddr,
+			      inet_addr_type(saddr) == RTN_LOCAL)) {
 			/* saddr should be known to target */
 			if (inet_addr_onlink(in_dev, target, saddr))
 				break;
@@ -360,6 +375,12 @@
 		break;
 	}
 
+get:
+	if (dev2) {
+		if (in_dev2)
+			in_dev_put(in_dev2);
+		dev_put(dev2);
+	}
 	if (in_dev)
 		in_dev_put(in_dev);
 	if (!saddr)
@@ -437,6 +458,26 @@
 	return flag; 
 } 
 
+static int arp_hidden(u32 tip, struct net_device *dev)
+{
+	struct net_device *dev2 = NULL;
+	struct in_device *in_dev2 = NULL;
+	int ret = 0;
+
+	if (!ipv4_devconf.hidden)
+		return 0;
+
+	if ((dev2 = ip_dev_find(tip)) && dev2 != dev &&
+	    (in_dev2 = in_dev_get(dev2)) && IN_DEV_HIDDEN(in_dev2))
+		ret = 1;
+	if (dev2) {
+		if (in_dev2)
+			in_dev_put(in_dev2);
+		dev_put(dev2);
+	}
+	return ret;
+}
+
 /* OBSOLETE FUNCTIONS */
 
 /*
@@ -831,6 +872,7 @@
 	if (sip == 0) {
 		if (arp->ar_op == htons(ARPOP_REQUEST) &&
 		    inet_addr_type(tip) == RTN_LOCAL &&
+		    !arp_hidden(tip, dev) &&
 		    !arp_ignore(in_dev,dev,sip,tip))
 			arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr);
 		goto out;
@@ -851,6 +893,8 @@
 					dont_send |= arp_ignore(in_dev,dev,sip,tip);
 				if (!dont_send && IN_DEV_ARPFILTER(in_dev))
 					dont_send |= arp_filter(sip,tip,dev); 
+				if (!dont_send && skb->pkt_type != PACKET_HOST)
+					dont_send |= arp_hidden(tip,dev); 
 				if (!dont_send)
 					arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
 
diff -ur v2.6.12/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v2.6.12/linux/net/ipv4/devinet.c	2005-06-18 08:50:52.000000000 +0300
+++ linux/net/ipv4/devinet.c	2005-06-18 09:56:39.556064992 +0300
@@ -822,7 +822,8 @@
 			continue;
 
 		for_primary_ifa(in_dev) {
-			if (ifa->ifa_scope != RT_SCOPE_LINK &&
+			if (!IN_DEV_HIDDEN(in_dev) &&
+			    ifa->ifa_scope != RT_SCOPE_LINK &&
 			    ifa->ifa_scope <= scope) {
 				addr = ifa->ifa_local;
 				goto out_unlock_both;
@@ -1349,6 +1350,14 @@
 			.proc_handler	= &proc_dointvec,
 		},
 		{
+			.ctl_name	= NET_IPV4_CONF_HIDDEN,
+			.procname	= "hidden",
+			.data		= &ipv4_devconf.hidden,
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= &proc_dointvec,
+		},
+		{
 			.ctl_name	= NET_IPV4_CONF_ARPFILTER,
 			.procname	= "arp_filter",
 			.data		= &ipv4_devconf.arp_filter,
@@ -1373,6 +1382,14 @@
 			.proc_handler	= &proc_dointvec,
 		},
 		{
+			.ctl_name	= NET_IPV4_CONF_FORWARD_SHARED,
+			.procname	= "forward_shared",
+			.data		= &ipv4_devconf.forward_shared,
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= &proc_dointvec,
+		},
+		{
 			.ctl_name	= NET_IPV4_CONF_NOXFRM,
 			.procname	= "disable_xfrm",
 			.data		= &ipv4_devconf.no_xfrm,
diff -ur v2.6.12/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- v2.6.12/linux/net/ipv4/fib_frontend.c	2005-03-03 10:17:23.000000000 +0200
+++ linux/net/ipv4/fib_frontend.c	2005-06-18 09:56:39.557064840 +0300
@@ -159,7 +159,8 @@
  */
 
 int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
-			struct net_device *dev, u32 *spec_dst, u32 *itag)
+			struct net_device *dev, u32 *spec_dst, u32 *itag,
+			int our)
 {
 	struct in_device *in_dev;
 	struct flowi fl = { .nl_u = { .ip4_u =
@@ -170,6 +171,7 @@
 	struct fib_result res;
 	int no_addr, rpf;
 	int ret;
+	int fwdsh = 0;
 
 	no_addr = rpf = 0;
 	rcu_read_lock();
@@ -177,6 +179,7 @@
 	if (in_dev) {
 		no_addr = in_dev->ifa_list == NULL;
 		rpf = IN_DEV_RPFILTER(in_dev);
+		fwdsh = IN_DEV_FORWARD_SHARED(in_dev);
 	}
 	rcu_read_unlock();
 
@@ -185,7 +188,12 @@
 
 	if (fib_lookup(&fl, &res))
 		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)
 		goto e_inval_res;
 	*spec_dst = FIB_RES_PREFSRC(res);
 	fib_combine_itag(itag, &res);
@@ -205,6 +213,8 @@
 	if (rpf)
 		goto e_inval;
 	fl.oif = dev->ifindex;
+	if (fwdsh)
+		fl.iif = loopback_dev.ifindex;
 
 	ret = 0;
 	if (fib_lookup(&fl, &res) == 0) {
diff -ur v2.6.12/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.6.12/linux/net/ipv4/route.c	2005-06-18 08:50:52.000000000 +0300
+++ linux/net/ipv4/route.c	2005-06-18 09:56:39.558064688 +0300
@@ -1572,7 +1572,7 @@
 			goto e_inval;
 		spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
 	} else if (fib_validate_source(saddr, 0, tos, 0,
-					dev, &spec_dst, &itag) < 0)
+					dev, &spec_dst, &itag, our) < 0)
 		goto e_inval;
 
 	rth = dst_alloc(&ipv4_dst_ops);
@@ -1686,7 +1686,7 @@
 
 
 	err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res), 
-				  in_dev->dev, &spec_dst, &itag);
+				  in_dev->dev, &spec_dst, &itag, 0);
 	if (err < 0) {
 		ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, 
 					 saddr);
@@ -1923,7 +1923,7 @@
 		int result;
 		result = fib_validate_source(saddr, daddr, tos,
 					     loopback_dev.ifindex,
-					     dev, &spec_dst, &itag);
+					     dev, &spec_dst, &itag, 1);
 		if (result < 0)
 			goto martian_source;
 		if (result)
@@ -1957,7 +1957,7 @@
 		spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
 	else {
 		err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst,
-					  &itag);
+					  &itag, 1);
 		if (err < 0)
 			goto martian_source;
 		if (err)
