--- linux/include/linux/inetdevice.h.orig	Tue Jan  5 01:31:35 1999
+++ linux/include/linux/inetdevice.h	Tue Nov 23 10:11:32 1999
@@ -16,6 +16,7 @@
 	int	log_martians;
 	int	forwarding;
 	int	mc_forwarding;
+	int	arp_invisible;
 	void	*sysctl;
 };
 
@@ -40,6 +41,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_ARP_INVISIBLE(in_dev)	(ipv4_devconf.arp_invisible && (in_dev)->cnf.arp_invisible)
 #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)
--- linux/include/linux/sysctl.h.orig	Tue Nov 23 10:10:42 1999
+++ linux/include/linux/sysctl.h	Tue Nov 23 10:11:32 1999
@@ -267,7 +267,8 @@
 	NET_IPV4_CONF_RP_FILTER=8,
 	NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE=9,
 	NET_IPV4_CONF_BOOTP_RELAY=10,
-	NET_IPV4_CONF_LOG_MARTIANS=11
+	NET_IPV4_CONF_LOG_MARTIANS=11,
+	NET_IPV4_CONF_ARP_INVISIBLE=12
 };
 
 /* /proc/sys/net/ipv6 */
--- linux/net/ipv4/arp.c.orig	Tue Nov 23 09:47:26 1999
+++ linux/net/ipv4/arp.c	Tue Nov 23 12:38:09 1999
@@ -65,6 +65,8 @@
  *					clean up the APFDDI & gen. FDDI bits.
  *		Alexey Kuznetsov:	new arp state machine;
  *					now it is in net/core/neighbour.c.
+ *		Julian Anastasov:	arp_invisible flag: hide the
+ *					interface and don't reply for it
  */
 
 /* RFC1122 Status:
@@ -305,16 +307,31 @@
 
 static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
 {
-	u32 saddr;
+	u32 saddr, saddr2;
 	u8  *dst_ha = NULL;
 	struct device *dev = neigh->dev;
+	struct device *dev2;
+	struct in_device *in_dev = NULL;
 	u32 target = *(u32*)neigh->primary_key;
 	int probes = neigh->probes;
 
-	if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL)
+	if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL) {
 		saddr = skb->nh.iph->saddr;
-	else
-		saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);
+		dev2 = ip_dev_find(saddr);
+		if (dev2) in_dev = dev2->ip_ptr;
+	}
+	if (!in_dev || IN_DEV_ARP_INVISIBLE(in_dev)) {
+		saddr2 = inet_select_addr(dev, target, RT_SCOPE_LINK);
+		if (!in_dev) saddr = saddr2;
+		in_dev = dev->ip_ptr;
+		if (!in_dev || IN_DEV_ARP_INVISIBLE(in_dev)) {
+			saddr2 = 0;
+		}
+		if ((saddr != saddr2) && net_ratelimit()) {
+			printk(KERN_INFO "%s: src ip=%d.%d.%d.%d is hidden, selecting %d.%d.%d.%d\n", __FUNCTION__, NIPQUAD(saddr), NIPQUAD(saddr2));
+		}
+		saddr = saddr2;
+	}
 
 	if ((probes -= neigh->parms->ucast_probes) < 0) {
 		if (!(neigh->nud_state&NUD_VALID))
@@ -542,6 +559,8 @@
 	u16 dev_type = dev->type;
 	int addr_type;
 	struct in_device *in_dev = dev->ip_ptr;
+	struct in_device *in_dev2;
+	struct device *tdev;
 	struct neighbour *n;
 
 /*
@@ -654,8 +673,17 @@
 	/* Special case: IPv4 duplicate address detection packet (RFC2131) */
 	if (sip == 0) {
 		if (arp->ar_op == __constant_htons(ARPOP_REQUEST) &&
-		    inet_addr_type(tip) == RTN_LOCAL)
-			arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr);
+		    inet_addr_type(tip) == RTN_LOCAL) {
+			in_dev2 = NULL;
+			tdev = ip_dev_find(tip);
+			if (tdev) in_dev2 = (struct in_device *) tdev->ip_ptr;
+			/*
+			 * In fact, we allow remote host to use this IP
+			 * if our interface is "hidden"
+			 */
+			if (in_dev2 && !IN_DEV_ARP_INVISIBLE(in_dev2))
+				arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr);
+		}
 		goto out;
 	}
 
@@ -668,7 +696,15 @@
 		if (addr_type == RTN_LOCAL) {
 			n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
 			if (n) {
-				arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+				in_dev2 = NULL;
+				tdev = ip_dev_find(tip);
+				if (tdev) in_dev2 = tdev->ip_ptr;
+				if (in_dev2 && IN_DEV_ARP_INVISIBLE(in_dev2) &&
+					net_ratelimit()) {
+					printk(KERN_INFO "%s: Skipping reply to %d.%d.%d.%d for hidden IP %d.%d.%d.%d\n", __FUNCTION__, NIPQUAD(sip), NIPQUAD(tip));
+				}
+				if (in_dev2 && !IN_DEV_ARP_INVISIBLE(in_dev2))
+					arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
 				neigh_release(n);
 			}
 			goto out;
--- linux/net/ipv4/devinet.c.orig	Tue Nov 23 09:46:40 1999
+++ linux/net/ipv4/devinet.c	Tue Nov 23 10:11:32 1999
@@ -923,7 +923,7 @@
 static struct devinet_sysctl_table
 {
 	struct ctl_table_header *sysctl_header;
-	ctl_table devinet_vars[12];
+	ctl_table devinet_vars[13];
 	ctl_table devinet_dev[2];
 	ctl_table devinet_conf_dir[2];
 	ctl_table devinet_proto_dir[2];
@@ -956,6 +956,9 @@
          &proc_dointvec},
 	{NET_IPV4_CONF_PROXY_ARP, "proxy_arp",
          &ipv4_devconf.proxy_arp, sizeof(int), 0644, NULL,
+         &proc_dointvec},
+	{NET_IPV4_CONF_ARP_INVISIBLE, "arp_invisible",
+         &ipv4_devconf.arp_invisible, sizeof(int), 0644, NULL,
          &proc_dointvec},
 	{NET_IPV4_CONF_BOOTP_RELAY, "bootp_relay",
          &ipv4_devconf.bootp_relay, sizeof(int), 0644, NULL,
--- linux/Documentation/networking/ip-sysctl.txt.orig	Tue Nov 23 09:45:08 1999
+++ linux/Documentation/networking/ip-sysctl.txt	Tue Nov 23 10:11:32 1999
@@ -156,6 +156,9 @@
 proxy_arp - BOOLEAN
 	Do proxy arp.
 
+arp_invisible - BOOLEAN
+	Hide this interface and don't send ARP replies for it.
+
 shared_media - BOOLEAN
 	undocumented.
 
--- linux/Documentation/proc.txt.orig	Tue Nov 23 09:43:28 1999
+++ linux/Documentation/proc.txt	Tue Nov 23 10:11:32 1999
@@ -1163,6 +1163,9 @@
 proxy_arp
    Do (1) or don't (0) do proxy ARP.
 
+arp_invisible
+   Hide this interface and don't send ARP replies for it.
+
 rp_filter
    Integer value deciding if source validation should be made. 
    1 means yes, 0 means no. Disabled by default, but 
