diff -urp v2.6.34/linux/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt
--- v2.6.34/linux/Documentation/networking/ip-sysctl.txt	2010-05-17 10:48:46.000000000 +0300
+++ linux/Documentation/networking/ip-sysctl.txt	2010-05-18 09:42:04.000000000 +0300
@@ -693,6 +693,17 @@ accept_redirects - BOOLEAN
 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.
@@ -900,6 +911,13 @@ disable_policy - BOOLEAN
 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
diff -urp v2.6.34/linux/include/linux/inetdevice.h linux/include/linux/inetdevice.h
--- v2.6.34/linux/include/linux/inetdevice.h	2010-05-17 10:49:00.000000000 +0300
+++ linux/include/linux/inetdevice.h	2010-05-18 09:45:05.000000000 +0300
@@ -32,6 +32,8 @@ enum
 	IPV4_DEVCONF_ARP_ANNOUNCE,
 	IPV4_DEVCONF_ARP_IGNORE,
 	IPV4_DEVCONF_PROMOTE_SECONDARIES,
+	IPV4_DEVCONF_FORWARD_SHARED,
+	IPV4_DEVCONF_HIDDEN,
 	IPV4_DEVCONF_ARP_ACCEPT,
 	IPV4_DEVCONF_ARP_NOTIFY,
 	IPV4_DEVCONF_ACCEPT_LOCAL,
@@ -114,6 +116,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)
 
@@ -137,6 +140,7 @@ static inline void ipv4_devconf_setall(s
 	  IN_DEV_ORCONF((in_dev), ACCEPT_REDIRECTS)))
 
 #define IN_DEV_ARPFILTER(in_dev)	IN_DEV_ORCONF((in_dev), ARPFILTER)
+#define IN_DEV_HIDDEN(in_dev)		IN_DEV_ANDCONF((in_dev), HIDDEN)
 #define IN_DEV_ARP_ANNOUNCE(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_ANNOUNCE)
 #define IN_DEV_ARP_IGNORE(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_IGNORE)
 #define IN_DEV_ARP_NOTIFY(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_NOTIFY)
diff -urp v2.6.34/linux/include/net/ip_fib.h linux/include/net/ip_fib.h
--- v2.6.34/linux/include/net/ip_fib.h	2010-02-25 09:01:36.000000000 +0200
+++ linux/include/net/ip_fib.h	2010-05-18 09:42:04.000000000 +0300
@@ -214,7 +214,7 @@ extern const struct nla_policy rtm_ipv4_
 extern void		ip_fib_init(void);
 extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
 			       struct net_device *dev, __be32 *spec_dst,
-			       u32 *itag, u32 mark);
+			       u32 *itag, u32 mark, int our);
 extern void fib_select_default(struct net *net, const struct flowi *flp,
 			       struct fib_result *res);
 
diff -urp v2.6.34/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.6.34/linux/net/ipv4/arp.c	2010-05-17 10:49:01.000000000 +0300
+++ linux/net/ipv4/arp.c	2010-05-18 09:46:08.000000000 +0300
@@ -71,6 +71,8 @@
  *					sending (e.g. insert 8021q tag).
  *		Harald Welte	:	convert to make use of jenkins hash
  *		Jesper D. Brouer:       Proxy ARP PVLAN RFC 3069 support.
+ *		Julian Anastasov:	"hidden" flag: hide the
+ *					interface and don't reply for it
  */
 
 #include <linux/module.h>
@@ -334,21 +336,34 @@ static void arp_solicit(struct neighbour
 	__be32 target = *(__be32*)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(dev_net(dev), ip_hdr(skb)->saddr)) != NULL &&
+	    (saddr = ip_hdr(skb)->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(dev_net(dev), ip_hdr(skb)->saddr) == RTN_LOCAL)
 			saddr = ip_hdr(skb)->saddr;
 		break;
 	case 1:		/* Restrict announcements of saddr in same subnet */
 		if (!skb)
 			break;
-		saddr = ip_hdr(skb)->saddr;
-		if (inet_addr_type(dev_net(dev), saddr) == RTN_LOCAL) {
+		if (saddr || (saddr = ip_hdr(skb)->saddr,
+			      inet_addr_type(dev_net(dev), saddr) == RTN_LOCAL)) {
 			/* saddr should be known to target */
 			if (inet_addr_onlink(in_dev, target, saddr))
 				break;
@@ -359,6 +374,12 @@ static void arp_solicit(struct neighbour
 		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)
@@ -435,6 +456,26 @@ static int arp_filter(__be32 sip, __be32
 	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_ALL(dev_net(dev), HIDDEN))
+		return 0;
+
+	if ((dev2 = ip_dev_find(dev_net(dev), 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 */
 
 /*
@@ -847,6 +888,7 @@ static int arp_process(struct sk_buff *s
 	if (sip == 0) {
 		if (arp->ar_op == htons(ARPOP_REQUEST) &&
 		    inet_addr_type(net, tip) == RTN_LOCAL &&
+		    !arp_hidden(tip, dev) &&
 		    !arp_ignore(in_dev, sip, tip))
 			arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
 				 dev->dev_addr, sha);
@@ -866,6 +908,8 @@ static int arp_process(struct sk_buff *s
 				dont_send |= arp_ignore(in_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) {
 				n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
 				if (n) {
diff -urp v2.6.34/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v2.6.34/linux/net/ipv4/devinet.c	2010-05-17 10:49:01.000000000 +0300
+++ linux/net/ipv4/devinet.c	2010-05-18 09:42:04.000000000 +0300
@@ -897,7 +897,8 @@ no_in_dev:
 			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;
@@ -1409,6 +1410,8 @@ static struct devinet_sysctl_table {
 		DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"),
 		DEVINET_SYSCTL_RW_ENTRY(LOG_MARTIANS, "log_martians"),
 		DEVINET_SYSCTL_RW_ENTRY(TAG, "tag"),
+		DEVINET_SYSCTL_RW_ENTRY(HIDDEN, "hidden"),
+		DEVINET_SYSCTL_RW_ENTRY(FORWARD_SHARED, "forward_shared"),
 		DEVINET_SYSCTL_RW_ENTRY(ARPFILTER, "arp_filter"),
 		DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"),
 		DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"),
diff -urp v2.6.34/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- v2.6.34/linux/net/ipv4/fib_frontend.c	2010-05-17 10:49:01.000000000 +0300
+++ linux/net/ipv4/fib_frontend.c	2010-05-18 09:42:04.000000000 +0300
@@ -231,7 +231,7 @@ unsigned int inet_dev_addr_type(struct n
 
 int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
 			struct net_device *dev, __be32 *spec_dst,
-			u32 *itag, u32 mark)
+			u32 *itag, u32 mark, int our)
 {
 	struct in_device *in_dev;
 	struct flowi fl = { .nl_u = { .ip4_u =
@@ -244,6 +244,7 @@ int fib_validate_source(__be32 src, __be
 	struct fib_result res;
 	int no_addr, rpf, accept_local;
 	int ret;
+	int fwdsh = 0;
 	struct net *net;
 
 	no_addr = rpf = accept_local = 0;
@@ -255,6 +256,7 @@ int fib_validate_source(__be32 src, __be
 		accept_local = IN_DEV_ACCEPT_LOCAL(in_dev);
 		if (mark && !IN_DEV_SRC_VMARK(in_dev))
 			fl.mark = 0;
+		fwdsh = IN_DEV_FORWARD_SHARED(in_dev);
 	}
 	rcu_read_unlock();
 
@@ -264,6 +266,13 @@ int fib_validate_source(__be32 src, __be
 	net = dev_net(dev);
 	if (fib_lookup(net, &fl, &res))
 		goto last_resort;
+	if (fwdsh) {
+		fwdsh = (res.type == RTN_LOCAL && !our);
+		if (fwdsh) {
+			rpf = 0;
+			accept_local = 1;
+		}
+	}
 	if (res.type != RTN_UNICAST) {
 		if (res.type != RTN_LOCAL || !accept_local)
 			goto e_inval_res;
@@ -286,6 +295,8 @@ int fib_validate_source(__be32 src, __be
 	if (rpf == 1)
 		goto e_inval;
 	fl.oif = dev->ifindex;
+	if (fwdsh)
+		fl.iif = net->loopback_dev->ifindex;
 
 	ret = 0;
 	if (fib_lookup(net, &fl, &res) == 0) {
diff -urp v2.6.34/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.6.34/linux/net/ipv4/route.c	2010-05-17 10:49:01.000000000 +0300
+++ linux/net/ipv4/route.c	2010-05-18 09:42:04.000000000 +0300
@@ -1890,7 +1890,7 @@ static int ip_route_input_mc(struct sk_b
 			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) < 0)
+					dev, &spec_dst, &itag, 0, our) < 0)
 		goto e_inval;
 
 	rth = dst_alloc(&ipv4_dst_ops);
@@ -2004,7 +2004,7 @@ static int __mkroute_input(struct sk_buf
 
 
 	err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res),
-				  in_dev->dev, &spec_dst, &itag, skb->mark);
+				  in_dev->dev, &spec_dst, &itag, skb->mark, 0);
 	if (err < 0) {
 		ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr,
 					 saddr);
@@ -2184,7 +2184,7 @@ static int ip_route_input_slow(struct sk
 		int result;
 		result = fib_validate_source(saddr, daddr, tos,
 					     net->loopback_dev->ifindex,
-					     dev, &spec_dst, &itag, skb->mark);
+					     dev, &spec_dst, &itag, skb->mark, 1);
 		if (result < 0)
 			goto martian_source;
 		if (result)
@@ -2213,7 +2213,7 @@ brd_input:
 		spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
 	else {
 		err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst,
-					  &itag, skb->mark);
+					  &itag, skb->mark, 1);
 		if (err < 0)
 			goto martian_source;
 		if (err)
