Index: /branches/rel_apv_10_4_0_112_gail/usr/click/lib/libip/sip.c
===================================================================
--- /branches/rel_apv_10_4_0_112_gail/usr/click/lib/libip/sip.c	(revision 39063)
+++ /branches/rel_apv_10_4_0_112_gail/usr/click/lib/libip/sip.c	(working copy)
@@ -18510,7 +18510,9 @@
 {
     size_t len;
     int num;
-	int num2;
+    int num2;
+    char *buf = NULL;
+    int  buf_len;
 
     len = 4;
     if (sysctlbyname("net.inet.ip.rts_enable", &num, &len, NULL, 0)) {
@@ -18538,7 +18540,20 @@
 	return -1;
     }
 
-    printf("ip rts expire %d", num/HZ);
+    printf("ip rts expire %d\n", num/HZ);
+
+    buf = (char *)malloc(256);
+    if (buf == NULL) {
+        return -1;
+    }
+    if (rts_show_blacklist((void **) &buf, &buf_len)) {
+        return -1;
+    }
+    if (buf != NULL) {
+        printf("ip rts blacklist \"%s\"", buf);
+    } else {
+        printf("ip rts blacklist \"disable\"");
+    }
     return 0;
 }
 
@@ -18584,6 +18599,8 @@
     char *ret, *t;
     int num, num2;
     size_t len;
+    char *buf = NULL;
+    int  buf_len;
 
     ret = (char *)malloc(256);
     if (ret == NULL) {
@@ -18621,7 +18638,22 @@
 	return ret;
     }
 
-    sprintf(t, "ip rts expire %d\n", num/HZ);
+    t += sprintf(t, "ip rts expire %d\n", num/HZ);
+
+    buf = (char *)malloc(256);
+    if (buf == NULL) {
+        return ret;
+    }
+
+    if (rts_show_blacklist((void **) &buf, &buf_len)) {
+        return ret;
+    }
+    if (buf != NULL) {
+        sprintf(t, "ip rts blacklist \"%s\"\n", buf);
+    } else {
+        sprintf(t, "ip rts blacklist \"disable\"\n");
+    }
+
     return ret;
 }
 
Index: /branches/rel_apv_10_4_0_112_gail/usr/click/lib/libparser/commands.pm
===================================================================
--- /branches/rel_apv_10_4_0_112_gail/usr/click/lib/libparser/commands.pm	(revision 39063)
+++ /branches/rel_apv_10_4_0_112_gail/usr/click/lib/libparser/commands.pm	(working copy)
@@ -19393,6 +19393,21 @@
 					optional => "YES",
 					default_value => "60",},
 		    ],
+	},
+	{
+		obj_type => "ITEM",
+		name => "blacklist",
+		menu => "root_ip_rts",
+		help_string => "Blacklist ip's for rts",
+		cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_KERN_API|CMD_NORMAL|CMD_MONITOR|CMD_GLOBAL",
+		user_level => "CLI_LEVEL_ENABLE",
+		function_name => "blacklist_ip_rts",
+		function_args => [{
+			type => "STRING",
+			help_string => "Please input the ip addresses you want to blacklist in the route entry seperated by comma or enter \\\"off\\\" to disable the blacklisting feature.",
+			optional => "NO",
+		},
+		],
 	},		
 	{
 		obj_type => "ITEM",
Index: /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/netinet/click_eroute.c
===================================================================
--- /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/netinet/click_eroute.c	(revision 39063)
+++ /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/netinet/click_eroute.c	(working copy)
@@ -25,6 +25,8 @@
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
 #include <netinet/ip_var.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/icmp6.h>
 #include <netinet/tcp.h>
 #include <netinet/tcpip.h>
 #include <netinet/tcp_fsm.h>
@@ -385,8 +387,6 @@
 uint32_t *ustat_ipf_overflow_num = ipf_overflow_num;
 uint32_t *ustat_rts_overflow_num = rts_overflow_num;
 
-pthread_mutex_t mutex;
-int counter = 0;
 #define RIRT_TABLE_LOCK(i) mtx_lock(&rirt_mtx[i])
 #define RIRT_TABLE_UNLOCK(i) mtx_unlock(&rirt_mtx[i])
 
@@ -10517,6 +10517,255 @@
 
 	return ret;
 }
+#define NS_INT16SZ			2
+#define NS_INADDRSZ			4
+#define NS_IN6ADDRSZ		16
+#define MAX_RTS_BLACKLIST	64
+int blacklisted = 0;
+int blk_count;
+char blk_list_str[MAX_RTS_BLACKLIST][MAX_RTS_BLACKLIST];
+
+static int inet_pton4(const char *src, unsigned char *dst)
+{
+	static const char digits[] = "0123456789";
+	int saw_digit, octets, ch;
+	unsigned char tmp[NS_INADDRSZ], *tp;
+
+	saw_digit = 0;
+	octets = 0;
+	*(tp = tmp) = 0;
+	while ((ch = *src++) != '\0') {
+		const char *pch;
+
+		if ((pch = strchr(digits, ch)) != NULL) {
+			unsigned int new = *tp * 10 + (pch - digits);
+
+			if (saw_digit && *tp == 0)
+				return (0);
+			if (new > 255)
+				return (0);
+			*tp = (unsigned char) new;
+			if (!saw_digit) {
+				if (++octets > 4)
+					return (0);
+				saw_digit = 1;
+			}
+		} else if (ch == '.' && saw_digit) {
+			if (octets == 4)
+				return (0);
+			*++tp = 0;
+			saw_digit = 0;
+		} else
+			return (0);
+	}
+	if (octets < 4)
+		return (0);
+	return (1);
+}
+
+static int is_inet4(const char*src)
+{
+	static const char digits[] = "0123456789";
+	int saw_digit, octets, ch;
+	unsigned char tmp[4], *tp;
+
+	saw_digit = 0;
+	octets = 0;
+	*(tp = tmp) = 0;
+	while ((ch = *src++) != '\0') {
+		const char *pch;
+
+		if ((pch = strchr(digits, ch)) != NULL) {
+			unsigned int new = *tp * 10 + (pch - digits);
+
+			if (saw_digit && *tp == 0)
+				return (0);
+			if (new > 255)
+				return (0);
+			*tp = (unsigned char) new;
+			if (!saw_digit) {
+				if (++octets > 4)
+					return (0);
+				saw_digit = 1;
+			}
+		} else if (ch == '.' && saw_digit) {
+			if (octets == 4)
+				return (0);
+			*++tp = 0;
+			saw_digit = 0;
+		} else
+			return (0);
+	}
+	if (octets < 4)
+		return (0);
+	return (1);
+}
+
+static int is_inet6(const char*src)
+{
+	static const char xdigits_l[] = "0123456789abcdef",
+				 xdigits_u[] = "0123456789ABCDEF";
+	unsigned char tmp[16], *tp, *endp, *colonp;
+	const char *xdigits, *curtok;
+	int ch, saw_xdigit;
+	unsigned int val;
+
+	memset((tp = tmp), '\0', 16);
+	endp = tp + 16;
+	colonp = NULL;
+	/* Leading :: requires some special handling. */
+	if (*src == ':')
+		if (*++src != ':')
+			return (0);
+	curtok = src;
+	saw_xdigit = 0;
+	val = 0;
+	while ((ch = *src++) != '\0') {
+		const char *pch;
+
+		if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+			pch = strchr((xdigits = xdigits_u), ch);
+		if (pch != NULL) {
+			val <<= 4;
+			val |= (pch - xdigits);
+			if (val > 0xffff)
+				return (0);
+			saw_xdigit = 1;
+			continue;
+		}
+		if (ch == ':') {
+			curtok = src;
+			if (!saw_xdigit) {
+				if (colonp)
+					return (0);
+				colonp = tp;
+				continue;
+			}
+			if (tp + NS_INT16SZ > endp)
+				return (0);
+			*tp++ = (unsigned char) ((val >> 8) & 0xff);
+			*tp++ = (unsigned char) (val & 0xff);
+			saw_xdigit = 0;
+			val = 0;
+			continue;
+		}
+		if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+				inet_pton4(curtok, tp) > 0) {
+			tp += NS_INADDRSZ;
+			saw_xdigit = 0;
+			break;  /* '\0' was seen by inet_pton4(). */
+		}
+		return (0);
+	}
+	if (saw_xdigit) {
+		if (tp + NS_INT16SZ > endp)
+			return (0);
+		*tp++ = (unsigned char) ((val >> 8) & 0xff);
+		*tp++ = (unsigned char) (val & 0xff);
+	}
+	if (colonp != NULL) {
+		/*
+		 * Since some memmove()'s erroneously fail to handle
+		 * overlapping regions, we'll do the shift by hand.
+		 */
+		const int n = tp - colonp;
+		int i;
+
+		if (tp == endp)
+			return (0);
+		for (i = 1; i <= n; i++) {
+			endp[- i] = colonp[n - i];
+			colonp[n - i] = 0;
+		}
+		tp = endp;
+	}
+	if (tp != endp)
+		return (0);
+	return (1);
+}
+
+static int is_ip(char *src)
+{
+	if (is_inet4(src) == 1 || is_inet6(src) == 1) {
+		return 1;
+	}
+
+	return 0;
+}
+
+int blacklist_ip_rts(void *pcb, char *ip_str)
+{
+	int ip_count = 0;
+	int len = strlen(ip_str);
+	int start = 0;
+	int end = 0;
+
+	if (ip_str[0] == '\0'){
+		app_printf(pcb, "please enter blacklisting ip address or off");
+		return EROUTE_CLI_OK;
+	}
+	if (strncmp(ip_str, "off", 3) == 0) {
+		blacklisted = 0;
+		return 0;
+	}
+
+	while (end <= len) {
+		if (ip_str[end] == ',' || ip_str[end] == '\0') {
+			strncpy(blk_list_str[ip_count], ip_str + start, end - start);
+			blk_list_str[ip_count][end - start] = '\0';
+
+			start = end + 1;
+			ip_count++;
+		}
+
+		end++;
+	}
+	blk_count = ip_count;
+	int i;
+	for ( i = 0; i < ip_count; i++) {
+		printf("blacklisted ips %d: %s\n", i + 1, blk_list_str[i]);
+		if (!is_ip(words[i])){
+			app_printf("Invalid input, please enter valid ip address\n");
+			return 1;
+		}
+	}
+
+	blacklisted = 1;
+	return 0;
+
+}
+
+int rts_show_blacklist( void *pcb, void **ptr, int32_t *len)
+{
+	int blklist_len = 0;
+	int i;
+	char *blk_ip_list;
+	*ptr = NULL;
+	*len = 0;
+	if (blacklisted) {
+		for (i = 0; i < blk_count; i++)
+		{
+			blklist_len += strlen(blk_list_str[i]) + 1;
+		}
+		blklist_len -= 1;
+		MALLOC(blk_ip_list, char*, blklist_len * sizeof(char), M_SLOW_EROUTE, M_NOWAIT|M_ZERO);
+		blk_ip_list[0] = '\0';
+
+		for (i = 0; i < blk_count; i++)
+		{
+			strcat(blk_ip_list, blk_list_str[i]);
+			if (i < blk_count - 1) {
+				strcat(blk_ip_list, ",");
+			}
+		}
+		*ptr = blk_ip_list;
+		*len = strlen(blk_ip_list) + 1;
+
+		printf("blk_ip_list = %s\n", (char *)*ptr);
+	}
+
+	return EROUTE_CLI_OK;
+}
 
 void
 rts_create(struct mbuf * m, void *ip_v, int flag)
@@ -10534,6 +10783,7 @@
 	struct ip6_hdr *ip6;
 	int isipv6;
 	int is_bsd = (flag & EROUTE_RTS_BSD);
+	int proto;
 	hash_t *table;
 
 	clicktcp_enter_func(m, NULL);
@@ -10564,6 +10814,7 @@
 
 		ori_key = RIRT_LK_V6(&local_ip6, &remote_ip6);
 		table = rirt_table_v6;
+		proto = ip6->ip6_nxt;
 	}else{
 		ip = (struct ip*)ip_v;
 		/* get ip header and flip ips because they need to match on the way back */
@@ -10575,43 +10826,81 @@
 
 		ori_key = RIRT_LK(&local_ip, &remote_ip);
 		table = rirt_table;
+		proto = ip->ip_p;
 	}
 
-	RIRT_TABLE_LOCK(RIRT_LI(ori_key));
-
-	pthread_mutex_init (&mutex,NULL);
-	pthread_mutex_lock(&mutex);
-	if ( counter < 50 ) {
-		struct in_addr myip1, myip2;
+	/* In case of TCP allow only SYN packets and for icmp allow only
+	 * echorequet to create an entry in rts table
+	 */
+	if (proto == IPPROTO_TCP) {
 		struct tcphdr *tcp;
-		struct udphdr *udp;
-		struct ether_header *eh = m->m_pkthdr.aext;
-		struct ifnet *ifp = m->m_pkthdr.rcvif;
-		const char *myip_str1= "172.20.12.50", *myip_str2 ="172.20.12.54";
-		inet_pton(AF_INET, myip_str1, &myip1);
-		inet_pton(AF_INET, myip_str2, &myip2);
-		if(ntohl(local_ip.s_addr) >= ntohl(myip1.s_addr) && ntohl(local_ip.s_addr) <= ntohl(myip2.s_addr) ){
-			fastlog_syslog(LOG_NOTICE,"IP:count = %d: %d, %d,%d, %d, %d",counter, ip->ip_hl, ntohs(ip->ip_len), ip->ip_p, ip->ip_src, ip->ip_dst);
-			fastlog_syslog(LOG_NOTICE,"MAC SRC= %s ", ether_sprintf(eh->ether_shost));
-			fastlog_syslog(LOG_NOTICE,"MAC DST=%s", ether_sprintf(eh->ether_dhost));
-			fastlog_syslog(LOG_NOTICE,"Interface: %s, rts_flag=%d", ifp->if_xname, flag);
-			switch (ip->ip_p) {
-			    case IPPROTO_TCP:
-			        tcp = (struct tcphdr*)((char *)ip + ip->ip_hl *4);
-			        fastlog_syslog(LOG_NOTICE,"tcp: %d, %d, %u, %u, %d, 0x%x", tcp->th_sport, tcp->th_dport, tcp->th_seq, tcp->th_ack, tcp->th_off*4, tcp->th_flags);
-			        break;
-			    case IPPROTO_UDP:
-			        udp = (struct udphdr*)((char *)ip + ip->ip_hl *4);
-			        fastlog_syslog(LOG_NOTICE,"udp: %d, %d, %d, 0x%x", udp->uh_sport, udp->uh_dport, udp->uh_ulen, udp->uh_sum);
-			        break;
-			    default:
-			        fastlog_syslog(LOG_NOTICE,"protocol: %d", ip->ip_p);
-			        break;
+		if (isipv6) {
+			tcp = (struct tcphdr *)(ip6 + 1);
+		} else {
+			tcp = (struct tcphdr*)((char *)ip + ip->ip_hl *4);
+		}
+		if ((tcp->th_flags != (TH_SYN | TH_ACK)) && (tcp->th_flags != TH_SYN)) {
+			flag = (flag | EROUTE_RTS_UPDATE);
+		} else if (tcp->th_flags  == (TH_SYN | TH_ACK)) {
+			return;
+		}
+	} else if (proto == IPPROTO_ICMP){
+		struct icmp *ih;
+		if (isipv6) {
+			ih =  (struct icmp *)(ip6 + 1);
+		} else {
+			ih = GETHDR(ip, icmp);
+		}
+		if (ih->icmp_type == ICMP_ECHOREPLY) {
+			return;
+		}
+	} else if (proto == IPPROTO_ICMPV6){
+		struct icmp6_hdr *ih6;
+		ih6 =  (struct icmp6_hdr *)(ip6 + 1);
+		if (ih6->icmp6_type == ICMP6_ECHO_REPLY) {
+			return;
+		}
+	}
+
+	/* Enable blacklisting ips from cli using "ip rts blacklist "ip1,ip2,.." ".
+	 * If these ip's are seen under destination ips just return without creating any entry
+	 */
+	if (blacklisted){
+		char local_ip_str[INET6_ADDRSTRLEN];
+		char remote_ip_str[INET6_ADDRSTRLEN];
+		int i;
+
+		fastlog_syslog(LOG_NOTICE,"rts_flag=%d", flag);
+		if (isipv6){
+			inet_ntop(AF_INET6, &local_ip6, local_ip_str, INET6_ADDRSTRLEN);
+			inet_ntop(AF_INET6, &remote_ip6, remote_ip_str, INET6_ADDRSTRLEN);
+		} else {
+			inet_ntop(AF_INET, &local_ip, local_ip_str, INET6_ADDRSTRLEN);
+			inet_ntop(AF_INET, &remote_ip, remote_ip_str, INET6_ADDRSTRLEN);
+		}
+		for( i = 0; i < blk_count; i++){
+			if (is_inet6(blk_list_str[i])) {
+				struct in6_addr blk_ip;
+				inet_pton(AF_INET6, blk_list_str[i], &blk_ip);
+				if(in6_addr_cmp(&local_ip6, &blk_ip) == 0){
+					fastlog_syslog(LOG_NOTICE,"blacklisted rts entry (remote %s, local %s)",
+							remote_ip_str, local_ip_str);
+					return;
+				}
+			} else if (is_inet4(blk_list_str[i])) {
+				struct in_addr blk_ip;
+				inet_aton(blk_list_str[i], &blk_ip);
+				if (local_ip.s_addr == blk_ip.s_addr){
+					fastlog_syslog(LOG_NOTICE,"blacklisted rts entry (remote %s, local %s)",
+							remote_ip_str, local_ip_str);
+					return;
+				}
 			}
-		counter++;
 		}
 	}
-	pthread_mutex_unlock(&mutex);
+
+	RIRT_TABLE_LOCK(RIRT_LI(ori_key));
+
 	/*
 	 * Note the insertion is done with temporary entry.  We *need* to
 	 * set hp->rec to a permanent entry if hp->new is true.
