Merge "IPACM: Change the method for preventing multiple instances of ipacm"
diff --git a/ipacm/inc/IPACM_ConntrackListener.h b/ipacm/inc/IPACM_ConntrackListener.h
index e5827f2..c1249c2 100644
--- a/ipacm/inc/IPACM_ConntrackListener.h
+++ b/ipacm/inc/IPACM_ConntrackListener.h
@@ -76,8 +76,6 @@
 	 int  CreateNatThreads(void);
 	 int  CreateConnTrackThreads(void);
 
-	 void HandleNeighIpAddrAddEvt(void *);
-	 void HandleNeighIpAddrDelEvt(void *);
 #ifdef CT_OPT
 	 void ProcessCTV6Message(void *);
 #endif
@@ -93,6 +91,9 @@
 	 {
 		return WanUp;
 	 }
+
+   void HandleNeighIpAddrAddEvt(ipacm_event_data_all *);
+   void HandleNeighIpAddrDelEvt(uint32_t);
 };
 
 extern IPACM_ConntrackListener *CtList;
diff --git a/ipacm/inc/IPACM_Conntrack_NATApp.h b/ipacm/inc/IPACM_Conntrack_NATApp.h
index 63af013..9eb9b4f 100644
--- a/ipacm/inc/IPACM_Conntrack_NATApp.h
+++ b/ipacm/inc/IPACM_Conntrack_NATApp.h
@@ -1,4 +1,4 @@
-/* 
+/*
 Copyright (c) 2013, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -112,6 +112,7 @@
 
 	int UpdatePwrSaveIf(uint32_t);
 	int ResetPwrSaveIf(uint32_t);
+        int DelEntriesOnClntDiscon(uint32_t);
 
 	void UpdateTcpUdpTo(uint32_t, int proto);
 
diff --git a/ipacm/src/IPACM_ConntrackListener.cpp b/ipacm/src/IPACM_ConntrackListener.cpp
index ae11d34..3559a8c 100644
--- a/ipacm/src/IPACM_ConntrackListener.cpp
+++ b/ipacm/src/IPACM_ConntrackListener.cpp
@@ -56,10 +56,6 @@
 	 IPACM_EvtDispatcher::registr(IPA_PROCESS_CT_MESSAGE_V6, this);
 	 IPACM_EvtDispatcher::registr(IPA_HANDLE_WLAN_UP, this);
 	 IPACM_EvtDispatcher::registr(IPA_HANDLE_LAN_UP, this);
-	 IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, this);
-	 IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, this);
-
-	IPACMDBG("creating conntrack threads\n");
 
 #ifdef CT_OPT
 	 p_lan2lan = IPACM_LanToLan::getLan2LanInstance();
@@ -121,28 +117,13 @@
 			IPACM_ConntrackClient::UpdateTCPFilters(data, false);
 			break;
 
-	 case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT:
-		 {
-			 IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT event\n");
-			 HandleNeighIpAddrAddEvt(data);
-		 }
-		 break;
-
-	 case IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT:
-		 {
-			 IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT event\n");
-			 HandleNeighIpAddrDelEvt(data);
-		 }
-		 break;
-
 	 default:
 			IPACMDBG("Ignore cmd %d\n", evt);
 			break;
 	 }
 }
-void IPACM_ConntrackListener::HandleNeighIpAddrAddEvt(void *in_param)
+void IPACM_ConntrackListener::HandleNeighIpAddrAddEvt(ipacm_event_data_all *data)
 {
-	ipacm_event_data_all *data = (ipacm_event_data_all *)in_param;
 	int fd = 0, len = 0, cnt, i, j;
 	struct ifreq ifr;
 	bool isNatIface = false;
@@ -152,6 +133,8 @@
 		IPACMDBG("Ignoring IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT EVENT\n");
 		return;
 	}
+
+  IPACMDBG("\n");
 	IPACMDBG("Received interface index %d with ip type: %d", data->if_index, data->iptype);
 	iptodot(" and ipv4 address", data->ipv4_addr);
 
@@ -165,9 +148,8 @@
 		}
 	}
 
+
 	cnt = pConfig->GetNatIfacesCnt();
-	if(NatIfaceCnt != cnt)
-	{
 		NatIfaceCnt = cnt;
 		if(pNatIfaces != NULL)
 		{
@@ -189,9 +171,8 @@
 			IPACMERR("Unable to retrieve non nat ifaces\n");
 			return;
 		}
+  IPACMDBG("Update %d Nat ifaces\n", NatIfaceCnt);
 
-		IPACMDBG("Update %d Nat ifaces", NatIfaceCnt);
-	}
 
 	/* Search/Configure linux interface-index and map it to IPA interface-index */
 	if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
@@ -265,37 +246,39 @@
 
 }
 
-void IPACM_ConntrackListener::HandleNeighIpAddrDelEvt(void *in_param)
+void IPACM_ConntrackListener::HandleNeighIpAddrDelEvt(uint32_t ipv4_addr)
 {
-	ipacm_event_data_all *data = (ipacm_event_data_all *)in_param;
 	int cnt;
 
-	if(data->ipv4_addr == 0 || data->iptype != IPA_IP_v4)
+	if(ipv4_addr == 0)
 	{
 		IPACMDBG("Ignoring IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT EVENT\n");
 		return;
 	}
-	IPACMDBG("Received interface index %d with ip type:%d", data->if_index, data->iptype);
+
+  IPACMDBG("\n");
+  iptodot("Received ip addr", ipv4_addr);
 	IPACMDBG("Entering NAT entry deletion checking\n");
 
 	for(cnt = 0; cnt<MAX_NAT_IFACES; cnt++)
 	{
-		if(nat_iface_ipv4_addr[cnt] == data->ipv4_addr)
+		if(nat_iface_ipv4_addr[cnt] == ipv4_addr)
 		{
-			IPACMDBG("Reseting ct filters of Interface (%d), entry (%d) ", data->if_index, cnt);
+			IPACMDBG("Reseting ct nat iface, entry (%d) ", cnt);
 			iptodot("with ipv4 address", nat_iface_ipv4_addr[cnt]);
 			nat_iface_ipv4_addr[cnt] = 0;
 		}
 
-		if(nonnat_iface_ipv4_addr[cnt] == data->ipv4_addr)
+		if(nonnat_iface_ipv4_addr[cnt] == ipv4_addr)
 		{
-			IPACMDBG("Reseting ct filters of Interface (%d), entry (%d) ", data->if_index, cnt);
+			IPACMDBG("Reseting ct filters, entry (%d) ", cnt);
 			iptodot("with ipv4 address", nonnat_iface_ipv4_addr[cnt]);
 			nonnat_iface_ipv4_addr[cnt] = 0;
 		}
 	}
 
-	nat_inst->FlushTempEntries(data->ipv4_addr, false);
+	nat_inst->FlushTempEntries(ipv4_addr, false);
+  nat_inst->DelEntriesOnClntDiscon(ipv4_addr);
 	return;
 }
 
@@ -303,7 +286,7 @@
 {
 	 ipacm_event_iface_up *wanup_data = (ipacm_event_iface_up *)in_param;
 
-	 IPACMDBG("Recevied below information during wanup, ");
+	 IPACMDBG("Recevied below information during wanup,\n");
 	 IPACMDBG("if_name:%s, ipv4_address:0x%x\n",
 						wanup_data->ifname, wanup_data->ipv4_addr);
 
@@ -362,6 +345,7 @@
 
 				 IPACMDBG("created UDP conntrack event listner thread\n");
 			}
+
 			isCTReg = true;
 	 }
 
diff --git a/ipacm/src/IPACM_Conntrack_NATApp.cpp b/ipacm/src/IPACM_Conntrack_NATApp.cpp
index 2424248..b55d7e9 100644
--- a/ipacm/src/IPACM_Conntrack_NATApp.cpp
+++ b/ipacm/src/IPACM_Conntrack_NATApp.cpp
@@ -1,4 +1,4 @@
-/* 
+/*
 Copyright (c) 2013, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -179,7 +179,7 @@
 	int cnt = 0;
 	IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__);
 
-	for(; cnt < curCnt; cnt++)
+	for(; cnt < max_entries; cnt++)
 	{
 		if(cache[cnt].private_ip == rule->private_ip &&
 			 cache[cnt].target_ip == rule->target_ip &&
@@ -230,16 +230,16 @@
 					return -1;
 				}
 
-				IPACMDBG("Deleted Nat entry Successfully\n");
+				IPACMDBG("Deleted Nat entry(%d) Successfully\n", cnt);
 			}
 			else
 			{
-				IPACMDBG("Deleted Nat entry only from cache\n");
+				IPACMDBG("Deleted Nat entry(%d) only from cache\n", cnt);
 			}
-			
+
 			memset(&cache[cnt], 0, sizeof(cache[cnt]));
 			curCnt--;
-			break; 
+			break;
 		}
 	}
 
@@ -306,7 +306,7 @@
 			nat_rule.private_port = rule->private_port;
 			nat_rule.public_port = rule->public_port;
 			nat_rule.protocol = rule->protocol;
-			
+
 			if(isPwrSaveIf(rule->private_ip) ||
 				 isPwrSaveIf(rule->target_ip))
 			{
@@ -346,8 +346,12 @@
 
 	if(cache[cnt].enabled == true)
 	{
-		IPACMDBG("Added rule successfully\n");
+		IPACMDBG("Added rule(%d) successfully\n", cnt);
 	}
+  else
+  {
+    IPACMDBG("Cached rule(%d) successfully\n", cnt);
+  }
 
 	return 0;
 }
@@ -379,7 +383,7 @@
 			return;
 		}
 	}
-	
+
 	nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET);
 	if(rule->protocol == IPPROTO_UDP)
 	{
@@ -416,9 +420,9 @@
 	iptodot("Source IP:", nfct_get_attr_u32(ct, ATTR_IPV4_SRC));
 	iptodot("Destination IP:",  nfct_get_attr_u32(ct, ATTR_IPV4_DST));
 	IPACMDBG("Source Port: %d, Destination Port: %d\n",
-					 nfct_get_attr_u16(ct, ATTR_PORT_SRC), nfct_get_attr_u16(ct, ATTR_PORT_DST)); 
-	
-	IPACMDBG("updating %d connection with time: %d\n", 
+					 nfct_get_attr_u16(ct, ATTR_PORT_SRC), nfct_get_attr_u16(ct, ATTR_PORT_DST));
+
+	IPACMDBG("updating %d connection with time: %d\n",
 					 rule->protocol, nfct_get_attr_u32(ct, ATTR_TIMEOUT));
 
 	ret = nfct_query(ct_hdl, NFCT_Q_UPDATE, ct);
@@ -440,7 +444,7 @@
 	int cnt;
 	uint32_t ts;
 
-	for(cnt = 0; cnt < curCnt; cnt++)
+	for(cnt = 0; cnt < max_entries; cnt++)
 	{
 		ts = 0;
 		if(cache[cnt].enabled == true)
@@ -458,7 +462,7 @@
 								                  cache[cnt].timestamp, ts);
 				continue;
 			}
-			
+
 			UpdateCTUdpTs(&cache[cnt], ts);
 		} /* end of outer if */
 
@@ -500,7 +504,7 @@
 int NatApp::UpdatePwrSaveIf(uint32_t client_lan_ip)
 {
 	int cnt;
-	IPACMDBG("\n");
+	IPACMDBG("Received IP address: 0x%x\n", client_lan_ip);
 
 	if(client_lan_ip == INVALID_IP_ADDR)
 	{
@@ -529,7 +533,7 @@
 		}
 	}
 
-	for(cnt = 0; cnt < curCnt; cnt++)
+	for(cnt = 0; cnt < max_entries; cnt++)
 	{
 		if(cache[cnt].private_ip == client_lan_ip &&
 			 cache[cnt].enabled == true)
@@ -553,7 +557,7 @@
 	int cnt;
 	ipa_nat_ipv4_rule nat_rule;
 
-	IPACMDBG("\n");
+	IPACMDBG("Received ip address: 0x%x\n", client_lan_ip);
 
 	if(client_lan_ip == INVALID_IP_ADDR)
 	{
@@ -570,7 +574,7 @@
 		}
 	}
 
-	for(cnt = 0; cnt < curCnt; cnt++)
+	for(cnt = 0; cnt < max_entries; cnt++)
 	{
 		if(cache[cnt].private_ip == client_lan_ip &&
 			 cache[cnt].enabled == false)
@@ -582,7 +586,7 @@
 			nat_rule.private_port = cache[cnt].private_port;
 			nat_rule.public_port = cache[cnt].public_port;
 			nat_rule.protocol = cache[cnt].protocol;
-			
+
 			if(ipa_nat_add_ipv4_rule(nat_table_hdl, &nat_rule, &cache[cnt].rule_hdl) < 0)
 			{
 				IPACMERR("unable to add the rule delete from cache\n");
@@ -710,3 +714,49 @@
 
 	return;
 }
+
+int NatApp::DelEntriesOnClntDiscon(uint32_t ip_addr)
+{
+ 	int cnt, tmp = curCnt;
+	IPACMDBG("Received IP address: 0x%x\n", ip_addr);
+
+	if(ip_addr == INVALID_IP_ADDR)
+	{
+		IPACMERR("Invalid ip address received\n");
+		return -1;
+	}
+
+	CHK_TBL_HDL();
+
+  for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++)
+  {
+    if(PwrSaveIfs[cnt] == ip_addr)
+    {
+      PwrSaveIfs[cnt] = 0;
+      IPACMDBG("Remove %d power save entry\n", cnt);
+      break;
+    }
+  }
+
+	for(cnt = 0; cnt < max_entries; cnt++)
+	{
+		if(cache[cnt].private_ip == ip_addr)
+		{
+
+      if(cache[cnt].enabled == true)
+      {
+			if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0)
+			{
+				IPACMERR("unable to delete the rule\n");
+				continue;
+			}
+      }
+
+			memset(&cache[cnt], 0, sizeof(cache[cnt]));
+      curCnt--;
+		}
+	}
+
+  IPACMDBG("Deleted %d entries\n", (tmp - curCnt));
+	return 0;
+}
diff --git a/ipacm/src/IPACM_Iface.cpp b/ipacm/src/IPACM_Iface.cpp
index 3f7aa5a..52bf19d 100644
--- a/ipacm/src/IPACM_Iface.cpp
+++ b/ipacm/src/IPACM_Iface.cpp
@@ -871,7 +871,7 @@
 
   memset(&ifr, 0, sizeof(struct ifreq));
   (void)strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
-  IPACMDBG_H("interface name (%s)\n", ifr.ifr_name);
+  IPACMDBG_H("interface name (%s)\n", if_name);
 
   if (ioctl(fd,SIOCGIFINDEX , &ifr) < 0)
   {
diff --git a/ipacm/src/IPACM_IfaceManager.cpp b/ipacm/src/IPACM_IfaceManager.cpp
index 0baeb00..bbce080 100644
--- a/ipacm/src/IPACM_IfaceManager.cpp
+++ b/ipacm/src/IPACM_IfaceManager.cpp
@@ -56,7 +56,9 @@
 	IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, this); 		// register for IPA_CFG_CHANGE event
 	IPACM_EvtDispatcher::registr(IPA_LINK_UP_EVENT, this);
 	IPACM_EvtDispatcher::registr(IPA_WLAN_AP_LINK_UP_EVENT, this);  // register for wlan AP-iface
+#ifndef FEATURE_IPA_ANDROID
 	IPACM_EvtDispatcher::registr(IPA_WLAN_STA_LINK_UP_EVENT, this); // register for wlan STA-iface
+#endif /* not defined(FEATURE_IPA_ANDROID)*/
 	IPACM_EvtDispatcher::registr(IPA_USB_LINK_UP_EVENT, this); // register for wlan STA-iface
 	return;
 }
@@ -227,20 +229,28 @@
 				IPACMDBG_H("Creating Wan interface\n");
 				IPACM_Wan *w = new IPACM_Wan(ipa_interface_index, is_sta_mode);
 				IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, w);
-#ifdef FEATURE_IPA_ANDROID
+//#ifdef FEATURE_IPA_ANDROID
+#if 0
 				IPACM_EvtDispatcher::registr(IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, w);
 				IPACM_EvtDispatcher::registr(IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, w);
-#else/* defined(FEATURE_IPA_ANDROID) */
+#endif
+//#else/* defined(FEATURE_IPA_ANDROID) */
 				IPACM_EvtDispatcher::registr(IPA_ROUTE_ADD_EVENT, w);
 				IPACM_EvtDispatcher::registr(IPA_ROUTE_DEL_EVENT, w);
-#endif /* not defined(FEATURE_IPA_ANDROID)*/
+//#endif /* not defined(FEATURE_IPA_ANDROID)*/
 				IPACM_EvtDispatcher::registr(IPA_FIREWALL_CHANGE_EVENT, w);
 				IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, w);
 				IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, w);
 				IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, w);
 				IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, w); 		// register for IPA_CFG_CHANGE event
-				IPACM_EvtDispatcher::registr(IPA_WLAN_LINK_DOWN_EVENT, w); // for STA mode
-				IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, w);
+				if(is_sta_mode == WLAN_WAN)
+				{
+					IPACM_EvtDispatcher::registr(IPA_WLAN_LINK_DOWN_EVENT, w); // for STA mode
+				}
+				else
+				{
+					IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, w);
+				}
 				IPACMDBG_H("ipa_WAN (%s):ipa_index (%d) instance open/registr ok\n", w->dev_name, w->ipa_if_num);
 				registr(ipa_interface_index, w);
 				/* solve the new_addr comes earlier issue */
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
index 0bfe4c7..851b181 100644
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -49,6 +49,8 @@
 #include "linux/rmnet_ipa_fd_ioctl.h"
 #include "linux/ipa_qmi_service_v01.h"
 #include "linux/msm_ipa.h"
+#include "IPACM_ConntrackListener.h"
+
 
 IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index)
 {
@@ -413,6 +415,11 @@
 					return;
 				}
 				handle_eth_client_route_rule(data->mac_addr, data->iptype);
+				if (data->iptype == IPA_IP_v4)
+				{
+					/* Add NAT rules after ipv4 RT rules are set */
+					CtList->HandleNeighIpAddrAddEvt(data);
+				}
 				return;
 			}
 		}
@@ -1284,11 +1291,13 @@
 			   }
 			   else
 			   {
-			     IPACMDBG_H("ipv4 addr for client:%d is changed \n", clnt_indx);
-			     delete_eth_rtrules(clnt_indx,IPA_IP_v4);
-		         get_client_memptr(eth_client, clnt_indx)->route_rule_set_v4 = false;
-			     get_client_memptr(eth_client, clnt_indx)->v4_addr = data->ipv4_addr;
-			}
+					IPACMDBG_H("ipv4 addr for client:%d is changed \n", clnt_indx);
+					/* delete NAT rules first */
+					CtList->HandleNeighIpAddrDelEvt(get_client_memptr(eth_client, clnt_indx)->v4_addr);
+					delete_eth_rtrules(clnt_indx,IPA_IP_v4);
+					get_client_memptr(eth_client, clnt_indx)->route_rule_set_v4 = false;
+					get_client_memptr(eth_client, clnt_indx)->v4_addr = data->ipv4_addr;
+				}
 		}
 	}
 	else
@@ -1555,19 +1564,19 @@
 	/* First reset nat rules and then route rules */
 	if(get_client_memptr(eth_client, clt_indx)->ipv4_set == true)
 	{
-	        IPACMDBG_H("Deleting Nat Rules\n");
-	        Nat_App->UpdatePwrSaveIf(get_client_memptr(eth_client, clt_indx)->v4_addr);
+			IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(eth_client, clt_indx)->v4_addr);
+			CtList->HandleNeighIpAddrDelEvt(get_client_memptr(eth_client, clt_indx)->v4_addr);
  	}
 
 	if (delete_eth_rtrules(clt_indx, IPA_IP_v4))
 	{
-		IPACMERR("unbale to delete ecm-client v4 route rules\n");
+		IPACMERR("unbale to delete ecm-client v4 route rules for index: %d\n", clt_indx);
 		return IPACM_FAILURE;
 	}
 
 	if (delete_eth_rtrules(clt_indx, IPA_IP_v6))
 	{
-		IPACMERR("unbale to delete ecm-client v6 route rules\n");
+		IPACMERR("unbale to delete ecm-client v6 route rules for index: %d\n", clt_indx);
 		return IPACM_FAILURE;
 	}
 
@@ -1704,8 +1713,26 @@
 	IPACMDBG_H("left %d eth clients need to be deleted \n ", num_eth_client);
 	for (i = 0; i < num_eth_client; i++)
 	{
-			delete_eth_rtrules(i, IPA_IP_v4);
-			delete_eth_rtrules(i, IPA_IP_v6);
+			/* First reset nat rules and then route rules */
+			if(get_client_memptr(eth_client, i)->ipv4_set == true)
+			{
+				IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(eth_client, i)->v4_addr);
+				CtList->HandleNeighIpAddrDelEvt(get_client_memptr(eth_client, i)->v4_addr);
+			}
+
+			if (delete_eth_rtrules(i, IPA_IP_v4))
+			{
+				IPACMERR("unbale to delete ecm-client v4 route rules for index %d\n", i);
+				res = IPACM_FAILURE;
+				goto fail;
+			}
+
+			if (delete_eth_rtrules(i, IPA_IP_v6))
+			{
+				IPACMERR("unbale to delete ecm-client v6 route rules for index %d\n", i);
+				res = IPACM_FAILURE;
+				goto fail;
+			}
 
 			IPACMDBG_H("Delete %d client header\n", num_eth_client);
 
diff --git a/ipacm/src/IPACM_Main.cpp b/ipacm/src/IPACM_Main.cpp
index 686d900..620e2fa 100644
--- a/ipacm/src/IPACM_Main.cpp
+++ b/ipacm/src/IPACM_Main.cpp
@@ -303,11 +303,15 @@
 		case SW_ROUTING_ENABLE:
 			IPACMDBG_H("Received SW_ROUTING_ENABLE\n");
 			evt_data.event = IPA_SW_ROUTING_ENABLE;
+			IPACMDBG_H("Not supported anymore\n");
+			return NULL;
 			break;
 
 		case SW_ROUTING_DISABLE:
 			IPACMDBG_H("Received SW_ROUTING_DISABLE\n");
 			evt_data.event = IPA_SW_ROUTING_DISABLE;
+			IPACMDBG_H("Not supported anymore\n");
+			return NULL;
 			break;
 
 		case WLAN_AP_CONNECT:
diff --git a/ipacm/src/IPACM_Netlink.cpp b/ipacm/src/IPACM_Netlink.cpp
index 34c1139..b5d7060 100644
--- a/ipacm/src/IPACM_Netlink.cpp
+++ b/ipacm/src/IPACM_Netlink.cpp
@@ -1502,6 +1502,12 @@
 			goto error;
 		}
 
+		if(msghdr== NULL)
+		{
+			IPACMERR(" failed to get msghdr\n");
+			goto error;
+		}
+
 		iov = msghdr->msg_iov;
 
 		memset(nlmsg, 0, sizeof(ipa_nl_msg_t));
@@ -1513,12 +1519,12 @@
 		/* Release NetLink message buffer */
 		if(msghdr)
 		{
-		ipa_nl_release_msg(msghdr);
+			ipa_nl_release_msg(msghdr);
 		}
 		if(nlmsg)
 		{
-		free(nlmsg);
-	}
+			free(nlmsg);
+		}
 	}
 
 	return IPACM_SUCCESS;
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
index 65dcca8..3d47598 100644
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.cpp
@@ -472,7 +472,8 @@
 		}
 		break;
 
-#ifdef FEATURE_IPA_ANDROID
+//#ifdef FEATURE_IPA_ANDROID
+#if 0
 	case IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT:
 		{
 			ipacm_event_data_iptype *data = (ipacm_event_data_iptype *)param;
@@ -568,7 +569,8 @@
 			}
 		}
 		break;
-#else/* defined(FEATURE_IPA_ANDROID) */
+#endif
+//#else/* defined(FEATURE_IPA_ANDROID) */
 	case IPA_ROUTE_ADD_EVENT:
 		{
 			ipacm_event_data_addr *data = (ipacm_event_data_addr *)param;
@@ -675,7 +677,7 @@
 			}
 		}
 		break;
-#endif /* not defined(FEATURE_IPA_ANDROID)*/
+//#endif /* not defined(FEATURE_IPA_ANDROID)*/
 	case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT:
 		{
 			ipacm_event_data_all *data = (ipacm_event_data_all *)param;
@@ -823,6 +825,11 @@
 				IPACMDBG_H("Setting up QMAP ID %d.\n", ext_prop->ext[0].mux_id);
 			}
 		}
+		else
+		{
+			IPACMERR("iface_query is empty.\n");
+			return IPACM_FAILURE;
+		}
 	}
 
     for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
@@ -3433,7 +3440,7 @@
 			goto fail;
 		}
 
-		if(num_ipv6_dest_flt_rule > 0)
+		if(num_ipv6_dest_flt_rule > 0 && num_ipv6_dest_flt_rule <= MAX_DEFAULT_v6_ROUTE_RULES)
 		{
 			if(m_filtering.DeleteFilteringHdls(ipv6_dest_flt_rule_hdl,  IPA_IP_v6, num_ipv6_dest_flt_rule) == false)
 			{
diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp
index 5cbcc4c..8c23025 100644
--- a/ipacm/src/IPACM_Wlan.cpp
+++ b/ipacm/src/IPACM_Wlan.cpp
@@ -48,6 +48,8 @@
 #include <IPACM_Wan.h>
 #include <IPACM_Lan.h>
 #include <IPACM_IfaceManager.h>
+#include <IPACM_ConntrackListener.h>
+
 
 /* static member to store the number of total wifi clients within all APs*/
 int IPACM_Wlan::total_num_wifi_clients = 0;
@@ -496,7 +498,9 @@
 				handle_wlan_client_route_rule(data->mac_addr, data->iptype);
 				if (data->iptype == IPA_IP_v4)
 				{
-					Nat_App->ResetPwrSaveIf(data->ipv4_addr);
+					/* Add NAT rules after ipv4 RT rules are set */
+					CtList->HandleNeighIpAddrAddEvt(data);
+//					Nat_App->ResetPwrSaveIf(data->ipv4_addr);
 				}
 			}
 		}
@@ -1407,6 +1411,8 @@
 			   else
 			   {
 			     IPACMDBG_H("ipv4 addr for client:%d is changed \n", clnt_indx);
+				 /* delete NAT rules first */
+				 CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, clnt_indx)->v4_addr);
 			     delete_default_qos_rtrules(clnt_indx,IPA_IP_v4);
 		         get_client_memptr(wlan_client, clnt_indx)->route_rule_set_v4 = false;
 			     get_client_memptr(wlan_client, clnt_indx)->v4_addr = data->ipv4_addr;
@@ -1721,19 +1727,19 @@
 	/* First reset nat rules and then route rules */
 	if(get_client_memptr(wlan_client, clt_indx)->ipv4_set == true)
 	{
-	        IPACMDBG_H("Deleting Nat Rules\n");
-	        Nat_App->UpdatePwrSaveIf(get_client_memptr(wlan_client, clt_indx)->v4_addr);
+	        IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wlan_client, clt_indx)->v4_addr);
+			CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, clt_indx)->v4_addr);
  	}
 
 	if (delete_default_qos_rtrules(clt_indx, IPA_IP_v4))
 	{
-		IPACMERR("unbale to delete v4 default qos route rules\n");
+		IPACMERR("unbale to delete v4 default qos route rules for index: %d\n", clt_indx);
 		return IPACM_FAILURE;
 	}
 
 	if (delete_default_qos_rtrules(clt_indx, IPA_IP_v6))
 	{
-		IPACMERR("unbale to delete v6 default qos route rules\n");
+		IPACMERR("unbale to delete v6 default qos route rules for indexn: %d\n", clt_indx);
 		return IPACM_FAILURE;
 	}
 
@@ -1996,8 +2002,26 @@
 
 	for (i = 0; i < num_wifi_client; i++)
 	{
-		delete_default_qos_rtrules(i, IPA_IP_v4);
-		delete_default_qos_rtrules(i, IPA_IP_v6);
+		/* First reset nat rules and then route rules */
+		if(get_client_memptr(wlan_client, i)->ipv4_set == true)
+		{
+	        IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wlan_client, i)->v4_addr);
+			CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, i)->v4_addr);
+		}
+
+		if (delete_default_qos_rtrules(i, IPA_IP_v4))
+		{
+			IPACMERR("unbale to delete v4 default qos route rules for index: %d\n", i);
+			res = IPACM_FAILURE;
+			goto fail;
+		}
+
+		if (delete_default_qos_rtrules(i, IPA_IP_v6))
+		{
+			IPACMERR("unbale to delete v6 default qos route rules for index: %d\n", i);
+			res = IPACM_FAILURE;
+			goto fail;
+		}
 
 		IPACMDBG_H("Delete %d client header\n", num_wifi_client);