diff -ur v2.4.28/linux/include/linux/in_route.h linux/include/linux/in_route.h
--- v2.4.28/linux/include/linux/in_route.h	1998-06-12 08:52:33.000000000 +0300
+++ linux/include/linux/in_route.h	2004-11-18 08:47:47.005576272 +0200
@@ -13,6 +13,7 @@
 #define RTCF_DIRECTDST	0x00020000
 #define RTCF_REDIRECTED	0x00040000
 #define RTCF_TPROXY	0x00080000
+#define RTCF_NOARP	0x00100000
 
 #define RTCF_FAST	0x00200000
 #define RTCF_MASQ	0x00400000
diff -ur v2.4.28/linux/include/linux/rtnetlink.h linux/include/linux/rtnetlink.h
--- v2.4.28/linux/include/linux/rtnetlink.h	2004-08-08 10:56:48.000000000 +0300
+++ linux/include/linux/rtnetlink.h	2004-11-18 08:47:47.006576120 +0200
@@ -171,6 +171,7 @@
 #define RTM_F_CLONED		0x200	/* This route is cloned		*/
 #define RTM_F_EQUALIZE		0x400	/* Multipath equalizer: NI	*/
 #define RTM_F_PREFIX		0x800	/* Prefix addresses		*/
+#define RTM_F_NOARP		0x1000	/* Disable ARP for this route	*/
 
 /* Reserved table identifiers */
 
@@ -323,6 +324,7 @@
 /* ifa_flags */
 
 #define IFA_F_SECONDARY		0x01
+#define IFA_F_HIDDEN		0x02
 
 #define IFA_F_DEPRECATED	0x20
 #define IFA_F_TENTATIVE		0x40
diff -ur v2.4.28/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.4.28/linux/net/ipv4/arp.c	2004-11-18 08:30:33.000000000 +0200
+++ linux/net/ipv4/arp.c	2004-11-18 08:48:03.425080128 +0200
@@ -71,6 +71,7 @@
  *					bonding can change the skb before
  *					sending (e.g. insert 8021q tag).
  *		Harald Welte	:	convert to make use of jenkins hash
+ *		Julian Anastasov:	Per-route ARP control
  */
 
 #include <linux/types.h>
@@ -323,21 +324,37 @@
 	u32 target = *(u32*)neigh->primary_key;
 	int probes = atomic_read(&neigh->probes);
 	struct in_device *in_dev = in_dev_get(dev);
+	struct rtable *rt;
 
 	if (!in_dev)
 		return;
 
+	/* Determine source IP for the probing packet. */
+	if (skb != NULL) {
+		rt = (struct rtable*)skb->dst;
+		if (rt && !rt->rt_iif && !(rt->rt_flags & RTCF_NOARP))
+			saddr = rt->rt_src;
+	}
+	if (!saddr) {
+		if (!ip_route_output(&rt, target, 0, 0, dev->ifindex)) {
+			saddr = rt->rt_src;
+			ip_rt_put(rt);
+		}
+	}
+
 	switch (IN_DEV_ARP_ANNOUNCE(in_dev)) {
 	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;
@@ -407,20 +424,35 @@
 	return !inet_confirm_addr(dev, sip, tip, scope);
 }
 
-static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev)
+static int arp_filter(struct sk_buff *skb, __u32 sip, __u32 tip,
+		struct in_device *in_dev)
 {
 	struct rtable *rt;
 	int flag = 0; 
-	/*unsigned long now; */
 
+	if (!IN_DEV_ARPFILTER(in_dev))
+		return 0;
+
+	/* Always answer direct queries. */
+	if (skb->pkt_type == PACKET_HOST)
+		return 0;
+
+	/* Then check routes:
+	 * primarily, this check is used to not to answer to some requests if
+	 * several interfaces are connected to the same segment.
+	 * This check also may be used for manual control of who sees IP
+	 * addresses at which link-level addresses by installing prohibiting
+	 * routes.  -- 2001/05/20  SAW
+	 */
 	if (ip_route_output(&rt, sip, tip, 0, 0) < 0) 
 		return 1;
-	if (rt->u.dst.dev != dev) { 
+	if (rt->u.dst.dev != in_dev->dev) { 
 		NET_INC_STATS_BH(ArpFilter);
 		flag = 1;
 	} 
 	ip_rt_put(rt); 
-	return flag; 
+
+	return flag;
 } 
 
 /* OBSOLETE FUNCTIONS */
@@ -861,9 +893,11 @@
 				int dont_send = 0;
 
 				if (!dont_send)
+					dont_send |= (rt->rt_flags & RTCF_NOARP);
+				if (!dont_send)
 					dont_send |= arp_ignore(in_dev,dev,sip,tip);
 				if (!dont_send && IN_DEV_ARPFILTER(in_dev))
-					dont_send |= arp_filter(sip,tip,dev); 
+					dont_send |= arp_filter(skb,sip,tip,in_dev); 
 				if (!dont_send)
 					arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
 
@@ -878,6 +912,9 @@
 				if (n)
 					neigh_release(n);
 
+				if (rt->rt_flags & RTCF_NOARP)
+					goto out;
+
 				if (skb->stamp.tv_sec == 0 ||
 				    skb->pkt_type == PACKET_HOST ||
 				    in_dev->arp_parms->proxy_delay == 0) {
diff -ur v2.4.28/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- v2.4.28/linux/net/ipv4/fib_frontend.c	2003-08-25 22:06:13.000000000 +0300
+++ linux/net/ipv4/fib_frontend.c	2004-11-18 08:47:47.009575664 +0200
@@ -445,6 +445,9 @@
 	req.rtm.rtm_protocol = RTPROT_KERNEL;
 	req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST);
 	req.rtm.rtm_type = type;
+	if (ifa->ifa_flags & IFA_F_HIDDEN && type == RTN_LOCAL &&
+	    cmd == RTM_NEWROUTE)
+		req.rtm.rtm_flags |= RTM_F_NOARP;
 
 	rta.rta_dst = &dst;
 	rta.rta_prefsrc = &ifa->ifa_local;
diff -ur v2.4.28/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.4.28/linux/net/ipv4/route.c	2004-11-18 08:30:33.000000000 +0200
+++ linux/net/ipv4/route.c	2004-11-18 08:47:47.010575512 +0200
@@ -1485,6 +1485,9 @@
 	if (res.type == RTN_BROADCAST)
 		goto brd_input;
 
+	if (res.fi && res.fi->fib_flags & RTM_F_NOARP)
+		flags |= RTCF_NOARP;
+
 	if (res.type == RTN_LOCAL) {
 		int result;
 		result = fib_validate_source(saddr, daddr, tos,
@@ -1922,6 +1925,9 @@
 	if (res.type == RTN_NAT)
 		goto e_inval;
 
+	if (res.fi && res.fi->fib_flags & RTM_F_NOARP)
+		flags |= RTCF_NOARP;
+
 	if (res.type == RTN_LOCAL) {
 		if (!key.src)
 			key.src = key.dst;
@@ -2125,6 +2131,8 @@
 	r->rtm_flags	= (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED;
 	if (rt->rt_flags & RTCF_NOTIFY)
 		r->rtm_flags |= RTM_F_NOTIFY;
+	if (rt->rt_flags & RTCF_NOARP)
+		r->rtm_flags |= RTM_F_NOARP;
 	RTA_PUT(skb, RTA_DST, 4, &rt->rt_dst);
 	if (rt->key.src) {
 		r->rtm_src_len = 32;
@@ -2249,6 +2257,8 @@
 	skb->dst = &rt->u.dst;
 	if (rtm->rtm_flags & RTM_F_NOTIFY)
 		rt->rt_flags |= RTCF_NOTIFY;
+	if (rtm->rtm_flags & RTM_F_NOARP)
+		rt->rt_flags |= RTCF_NOARP;
 
 	NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
 
