Merge "IPANAT: remove the syslog usage"
diff --git a/ipacm/inc/IPACM_Filtering.h b/ipacm/inc/IPACM_Filtering.h
index 48a3d66..7554ba9 100644
--- a/ipacm/inc/IPACM_Filtering.h
+++ b/ipacm/inc/IPACM_Filtering.h
@@ -69,7 +69,6 @@
 private:
 	static const char *DEVICE_NAME;
 	int fd; /* File descriptor of the IPA device node /dev/ipa */
-	int fd_wwan_ioctl;
 };
 
 #endif //IPACM_FILTERING_H
diff --git a/ipacm/inc/IPACM_Lan.h b/ipacm/inc/IPACM_Lan.h
index 92475cb..1f561fa 100644
--- a/ipacm/inc/IPACM_Lan.h
+++ b/ipacm/inc/IPACM_Lan.h
@@ -324,7 +324,11 @@
 	/*handle lan iface down event*/
 	int handle_down_evt();
 
-	void post_lan2lan_client_disconnect_msg();
+	/*handle lan2lan internal mesg posting*/
+	int post_lan2lan_client_disconnect_msg(ipa_ip_type iptype);
+
+	/*handle reset usb-client rt-rules */
+	int handle_lan_client_reset_rt(ipa_ip_type iptype);
 };
 
 #endif /* IPACM_LAN_H */
diff --git a/ipacm/inc/IPACM_Log.h b/ipacm/inc/IPACM_Log.h
index d468f96..8a05761 100644
--- a/ipacm/inc/IPACM_Log.h
+++ b/ipacm/inc/IPACM_Log.h
@@ -61,18 +61,18 @@
 
 static char buffer_send[MAX_BUF_LEN];
 
-#define PERROR(fmt)   memset(buffer_send, 0, sizeof(MAX_BUF_LEN));\
+#define PERROR(fmt)   memset(buffer_send, 0, MAX_BUF_LEN);\
 					  snprintf(buffer_send,MAX_BUF_LEN,"%s:%d %s()", __FILE__, __LINE__, __FUNCTION__);\
 					  ipacm_log_send (buffer_send); \
                       perror(fmt);
 
-#define IPACMERR(fmt, ...)	memset(buffer_send, 0, sizeof(MAX_BUF_LEN));\
+#define IPACMERR(fmt, ...)	memset(buffer_send, 0, MAX_BUF_LEN);\
 							snprintf(buffer_send,MAX_BUF_LEN,"ERR: %s:%d %s() " fmt, __FILE__,  __LINE__, __FUNCTION__, ##__VA_ARGS__);\
 							ipacm_log_send (buffer_send);
-#define IPACMDBG(fmt, ...)	memset(buffer_send, 0, sizeof(MAX_BUF_LEN));\
+#define IPACMDBG(fmt, ...)	memset(buffer_send, 0, MAX_BUF_LEN);\
 							snprintf(buffer_send,MAX_BUF_LEN,"%s:%d %s() " fmt, __FILE__,  __LINE__, __FUNCTION__, ##__VA_ARGS__);\
 							ipacm_log_send (buffer_send);
-#define IPACMLOG(fmt, ...)      memset(buffer_send, 0, sizeof(MAX_BUF_LEN));\
+#define IPACMLOG(fmt, ...)      memset(buffer_send, 0, MAX_BUF_LEN);\
                                                         snprintf(buffer_send,MAX_BUF_LEN, fmt, ##__VA_ARGS__);\
                                                         ipacm_log_send (buffer_send);
 
diff --git a/ipacm/inc/IPACM_Wan.h b/ipacm/inc/IPACM_Wan.h
index c677d79..b60bb26 100644
--- a/ipacm/inc/IPACM_Wan.h
+++ b/ipacm/inc/IPACM_Wan.h
@@ -49,7 +49,7 @@
 #include <IPACM_Defs.h>
 #include <IPACM_Xml.h>
 
-#define IPA_NUM_DEFAULT_WAN_FILTER_RULES 2
+#define IPA_NUM_DEFAULT_WAN_FILTER_RULES 3 /*1 for v4, 2 for v6*/
 #define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4 2
 #define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6 3
 
diff --git a/ipacm/inc/IPACM_Wlan.h b/ipacm/inc/IPACM_Wlan.h
index 631713a..1142772 100644
--- a/ipacm/inc/IPACM_Wlan.h
+++ b/ipacm/inc/IPACM_Wlan.h
@@ -214,7 +214,7 @@
 	int handle_wlan_client_init_ex(ipacm_event_data_wlan_ex *data);
 
 	/*handle lan2lan internal mesg posting*/
-	int handle_lan2lan_msg_post(uint8_t *mac_addr, ipa_cm_event_id event);
+	int handle_lan2lan_msg_post(uint8_t *mac_addr, ipa_cm_event_id event, ipa_ip_type iptype);
 
 	/*handle wifi client */
 	int handle_wlan_client_ipaddr(ipacm_event_data_all *data);
@@ -253,7 +253,11 @@
 	/* install UL filter rule from Q6 */
 	virtual int handle_uplink_filter_rule(ipacm_ext_prop* prop, ipa_ip_type iptype);
 
+	/* install TCP control filter rules */
 	virtual void install_tcp_ctl_flt_rule(ipa_ip_type iptype);
+
+	/*handle reset wifi-client rt-rules */
+	int handle_wlan_client_reset_rt(ipa_ip_type iptype);
 };
 
 
diff --git a/ipacm/src/Android.mk b/ipacm/src/Android.mk
new file mode 100644
index 0000000..5d06031
--- /dev/null
+++ b/ipacm/src/Android.mk
@@ -0,0 +1,80 @@
+ifneq (,$(filter $(QCOM_BOARD_PLATFORMS),$(TARGET_BOARD_PLATFORM)))
+ifneq (, $(filter aarch64 arm arm64, $(TARGET_ARCH)))
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../inc
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../ipanat/inc
+LOCAL_C_INCLUDES += external/icu4c/common
+LOCAL_C_INCLUDES += external/dhcpcd
+LOCAL_C_INCLUDES += bionic/libstdc++/include
+LOCAL_C_INCLUDES += external/libxml2/include
+LOCAL_C_INCLUDES += external/libnetfilter_conntrack/include
+LOCAL_C_INCLUDES += external/libnfnetlink/include
+
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+
+
+LOCAL_CFLAGS := -v
+LOCAL_CFLAGS += -DFEATURE_IPA_ANDROID
+LOCAL_CFLAGS += -DDEBUG
+
+ifeq ($(TARGET_ARCH),arm)
+LOCAL_CFLAGS += -include bionic/libc/kernel/arch-arm/asm/posix_types.h
+LOCAL_CFLAGS += -include bionic/libc/kernel/arch-arm/asm/byteorder.h
+endif
+
+LOCAL_SRC_FILES := IPACM_Main.cpp \
+		IPACM_EvtDispatcher.cpp \
+		IPACM_Config.cpp \
+		IPACM_CmdQueue.cpp \
+		IPACM_Filtering.cpp \
+		IPACM_Routing.cpp \
+		IPACM_Header.cpp \
+		IPACM_Lan.cpp \
+		IPACM_Iface.cpp \
+		IPACM_Wlan.cpp \
+		IPACM_Wan.cpp \
+		IPACM_IfaceManager.cpp \
+		IPACM_Neighbor.cpp \
+		IPACM_Netlink.cpp \
+		IPACM_Xml.cpp \
+		IPACM_Conntrack_NATApp.cpp\
+		IPACM_ConntrackClient.cpp \
+		IPACM_ConntrackListener.cpp \
+                IPACM_Log.cpp
+
+LOCAL_MODULE := ipacm
+LOCAL_MODULE_TAGS := debug
+
+LOCAL_SHARED_LIBRARIES := libipanat
+LOCAL_SHARED_LIBRARIES += libxml2
+LOCAL_SHARED_LIBRARIES += libnfnetlink
+LOCAL_SHARED_LIBRARIES += libnetfilter_conntrack
+LOCAL_SHARED_LIBRARIES += libicuuc
+LOCAL_SHARED_LIBRARIES += libdhcpcd
+include $(BUILD_EXECUTABLE)
+
+################################################################################
+
+define ADD_TEST
+
+include $(CLEAR_VARS)
+LOCAL_MODULE       := $1
+LOCAL_SRC_FILES    := $1
+LOCAL_MODULE_CLASS := ipacm
+LOCAL_MODULE_TAGS  := debug
+LOCAL_MODULE_PATH  := $(TARGET_OUT_ETC)
+include $(BUILD_PREBUILT)
+
+endef
+
+IPACM_FILE_LIST := IPACM_cfg.xml
+$(foreach TEST,$(IPACM_FILE_LIST),$(eval $(call ADD_TEST,$(TEST))))
+
+endif # $(TARGET_ARCH)
+endif
diff --git a/ipacm/src/IPACM_Filtering.cpp b/ipacm/src/IPACM_Filtering.cpp
index fac26a2..4882ebb 100644
--- a/ipacm/src/IPACM_Filtering.cpp
+++ b/ipacm/src/IPACM_Filtering.cpp
@@ -57,18 +57,11 @@
 	{
 		IPACMERR("Failed opening %s.\n", DEVICE_NAME);
 	}
-
-	fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
-	if(fd_wwan_ioctl < 0)
-	{
-		IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME);
-	}
 }
 
 IPACM_Filtering::~IPACM_Filtering()
 {
 	close(fd);
-	close(fd_wwan_ioctl);
 }
 
 bool IPACM_Filtering::DeviceNodeIsOpened()
@@ -238,16 +231,12 @@
 	int ret = 0, cnt, num_rules = 0, pos = 0;
 	ipa_install_fltr_rule_req_msg_v01 qmi_rule_msg;
 
+	int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
 	if(fd_wwan_ioctl < 0)
 	{
-		IPACMERR("WWAN ioctl is not open.\n");
+		IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME);
 		return false;
 	}
-	else
-	{
-		IPACMDBG("WWAN ioctl is open.\n");
-	}
-   
 
 	if(rule_table_v4 != NULL)
 	{
@@ -263,6 +252,7 @@
 	if(num_rules > QMI_IPA_MAX_FILTERS_V01)
 	{
 		IPACMERR("The number of filtering rules exceed limit.\n");
+		close(fd_wwan_ioctl);
 		return false;
 	}
 	else
@@ -329,20 +319,22 @@
 		if (ret != 0)
 		{
 			IPACMERR("Failed adding Filtering rule %p with ret %d\n ", &qmi_rule_msg, ret);
+			close(fd_wwan_ioctl);
 			return false;
 		}
 	}
 	IPACMDBG("Added Filtering rule %p\n", &qmi_rule_msg);
+	close(fd_wwan_ioctl);
 	return true;
 }
 
 bool IPACM_Filtering::SendFilteringRuleIndex(struct ipa_fltr_installed_notif_req_msg_v01* table)
 {
 	int ret = 0;
-
+	int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
 	if(fd_wwan_ioctl < 0)
 	{
-		IPACMERR("WWAN ioctl is not open.\n");
+		IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME);
 		return false;
 	}
 
@@ -350,10 +342,12 @@
 	if (ret != 0)
 	{
 		IPACMERR("Failed adding filtering rule index %p with ret %d\n", table, ret);
+		close(fd_wwan_ioctl);
 		return false;
 	}
 
 	IPACMDBG("Added Filtering rule index %p\n", table);
+	close(fd_wwan_ioctl);
 	return true;
 }
 
diff --git a/ipacm/src/IPACM_Iface.cpp b/ipacm/src/IPACM_Iface.cpp
index 6fb2e5c..293c311 100644
--- a/ipacm/src/IPACM_Iface.cpp
+++ b/ipacm/src/IPACM_Iface.cpp
@@ -511,6 +511,7 @@
 	if(iface_query == NULL)
 	{
 		IPACMERR("Unable to allocate iface_query memory.\n");
+		close(fd);
 		return IPACM_FAILURE;
 	}
 	IPACMDBG("iface name %s\n", dev_name);
@@ -531,6 +532,7 @@
 		if(tx_prop == NULL)
 		{
 			IPACMERR("Unable to allocate tx_prop memory.\n");
+			close(fd);
 			return IPACM_FAILURE;
 		}
 	memcpy(tx_prop->name, dev_name, sizeof(tx_prop->name));
@@ -562,6 +564,7 @@
 		if(rx_prop == NULL)
 		{
 			IPACMERR("Unable to allocate rx_prop memory.\n");
+			close(fd);
 			return IPACM_FAILURE;
 		}
 	memcpy(rx_prop->name, dev_name,
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
index fa6d101..1f967ea 100644
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -42,7 +42,6 @@
 #include <string.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
-#include <assert.h>
 #include "IPACM_Netlink.h"
 #include "IPACM_Lan.h"
 #include "IPACM_Wan.h"
@@ -247,35 +246,35 @@
 
 					if (IPACM_Wan::isWanUP())
 					{
+						if(data->iptype == IPA_IP_v4 || data->iptype == IPA_IP_MAX)
+						{
 						if(IPACM_Wan::backhaul_is_sta_mode == false)
 						{
-							if(data->iptype == IPA_IP_v4 || data->iptype == IPA_IP_MAX)
-							{
 								ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4);
 								handle_wan_up_ex(ext_prop, IPA_IP_v4);
 							}
-						}
 						else
 						{
 							handle_wan_up(IPA_IP_v4);
 						}
 					}
+					}
 
 					if(IPACM_Wan::isWanUP_V6())
 					{
+						if((data->iptype == IPA_IP_v6 || data->iptype == IPA_IP_MAX) && num_dft_rt_v6 == 1)
+						{
 						if(IPACM_Wan::backhaul_is_sta_mode == false)
 						{
-							if(data->iptype == IPA_IP_v6 || data->iptype == IPA_IP_MAX)
-							{
 								ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6);
 								handle_wan_up_ex(ext_prop, IPA_IP_v6);
 							}
-						}
 						else
 						{
 							handle_wan_up(IPA_IP_v6);
 						}
 					}
+					}
 
 					/* Post event to NAT */
 					if (data->iptype == IPA_IP_v4)
@@ -320,18 +319,18 @@
 			return;
 		}
 		IPACMDBG("Backhaul is sta mode?%d\n", data_wan->is_sta);
+		if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
+		{
 		if(data_wan->is_sta == false)
 		{
-			if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
-			{
 				ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4);
 				handle_wan_up_ex(ext_prop, IPA_IP_v4);
 			}
-		}
 		else
 		{
 			handle_wan_up(IPA_IP_v4);
 		}
+		}
 		break;
 
 	case IPA_HANDLE_WAN_UP_V6:
@@ -344,18 +343,18 @@
 			return;
 		}
 		IPACMDBG("Backhaul is sta mode?%d\n", data_wan->is_sta);
+		if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
+		{
 		if(data_wan->is_sta == false)
 		{
-			if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
-			{
 				ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6);
 				handle_wan_up_ex(ext_prop, IPA_IP_v6);
 			}
-		}
 		else
 		{
 			handle_wan_up(IPA_IP_v6);
 		}
+		}
 		break;
 
 	case IPA_HANDLE_WAN_DOWN:
@@ -378,6 +377,11 @@
 			IPACMERR("No event data is found.\n");
 			return;
 		}
+		/* clean up v6 RT rules*/
+		IPACMDBG("Received IPA_WAN_V6_DOWN in LAN-instance and need clean up client IPv6 address \n");
+		/* reset usb-client ipv6 rt-rules */
+		handle_lan_client_reset_rt(IPA_IP_v6);
+
 		IPACMDBG("Backhaul is sta mode?%d\n", data_wan->is_sta);
 		handle_wan_down_v6(data_wan->is_sta);
 		break;
@@ -1208,17 +1212,20 @@
 
 			}
 		}
+		/* initialize wifi client*/
+		get_client_memptr(eth_client, num_eth_client)->route_rule_set_v4 = false;
+		get_client_memptr(eth_client, num_eth_client)->route_rule_set_v6 = 0;
+		get_client_memptr(eth_client, num_eth_client)->ipv4_set = false;
+		get_client_memptr(eth_client, num_eth_client)->ipv6_set = 0;
+		num_eth_client++;
+		header_name_count++; //keep increasing header_name_count
+		res = IPACM_SUCCESS;
+		IPACMDBG("eth client number: %d\n", num_eth_client);
 	}
-	/* initialize wifi client*/
-	get_client_memptr(eth_client, num_eth_client)->route_rule_set_v4 = false;
-    get_client_memptr(eth_client, num_eth_client)->route_rule_set_v6 = 0;
-	get_client_memptr(eth_client, num_eth_client)->ipv4_set = false;
-    get_client_memptr(eth_client, num_eth_client)->ipv6_set = 0;
-	num_eth_client++;
-	header_name_count++; //keep increasing header_name_count
-	res = IPACM_SUCCESS;
-	IPACMDBG("eth client number: %d\n", num_eth_client);
-
+	else
+	{
+		return res;
+	}
 fail:
 	free(pHeaderDescriptor);
 
@@ -1831,7 +1838,8 @@
 	}
 
 	/* posting ip to lan2lan module to delete RT/FILTER rules*/
-	post_lan2lan_client_disconnect_msg();
+	post_lan2lan_client_disconnect_msg(IPA_IP_v4);
+	post_lan2lan_client_disconnect_msg(IPA_IP_v6);
 
 /* Delete private subnet*/
 #ifdef FEATURE_IPA_ANDROID
@@ -2494,7 +2502,6 @@
 		{
 			if(lan2lan_flt_rule_hdl_v4[i].rule_hdl == rule_hdl)
 			{
-				assert(lan2lan_flt_rule_hdl_v4[i].valid == true);
 				if(reset_to_dummy_flt_rule(IPA_IP_v4, rule_hdl) == IPACM_FAILURE)
 				{
 					IPACMERR("Failed to delete lan2lan v4 flt rule %d\n", rule_hdl);
@@ -2519,7 +2526,6 @@
 		{
 			if(lan2lan_flt_rule_hdl_v6[i].rule_hdl == rule_hdl)
 			{
-				assert(lan2lan_flt_rule_hdl_v6[i].valid == true);
 				if(reset_to_dummy_flt_rule(IPA_IP_v6, rule_hdl) == IPACM_FAILURE)
 				{
 					IPACMERR("Failed to delete lan2lan v6 flt rule %d\n", rule_hdl);
@@ -3115,7 +3121,47 @@
 	IPACM_EvtDispatcher::PostEvt(&evt);
 }
 
-void IPACM_Lan::post_lan2lan_client_disconnect_msg()
+/*handle reset usb-client rt-rules */
+int IPACM_Lan::handle_lan_client_reset_rt(ipa_ip_type iptype)
+{
+	int i, res = IPACM_SUCCESS;
+
+	/* clean eth-client routing rules */
+	IPACMDBG("left %d eth clients need to be deleted \n ", num_eth_client);
+	for (i = 0; i < num_eth_client; i++)
+	{
+		res = delete_eth_rtrules(i, iptype);
+		if (res != IPACM_SUCCESS)
+		{
+			IPACMERR("Failed to delete old iptype(%d) rules.\n", iptype);
+			return res;
+		}
+	} /* end of for loop */
+
+	/* Pass info to LAN2LAN module */
+	res = post_lan2lan_client_disconnect_msg(iptype);
+	if (res != IPACM_SUCCESS)
+	{
+		IPACMERR("Failed to posting delete old iptype(%d) address.\n", iptype);
+		return res;
+	}
+	/* Reset ip-address */
+	for (i = 0; i < num_eth_client; i++)
+	{
+		if(iptype == IPA_IP_v4)
+		{
+			get_client_memptr(eth_client, i)->ipv4_set = false;
+		}
+		else
+		{
+			get_client_memptr(eth_client, i)->ipv6_set = 0;
+		}
+	} /* end of for loop */
+	return res;
+}
+
+/*handle lan2lan internal mesg posting*/
+int IPACM_Lan::post_lan2lan_client_disconnect_msg(ipa_ip_type iptype)
 {
 	int i, j;
 	ipacm_cmd_q_data evt_data;
@@ -3123,13 +3169,14 @@
 
 	for (i = 0; i < num_eth_client; i++)
 	{
-			if(get_client_memptr(eth_client, i)->ipv4_set == true)
+			if((get_client_memptr(eth_client, i)->ipv4_set == true)
+				&& (iptype == IPA_IP_v4))
 			{
 				lan_client = (ipacm_event_lan_client*)malloc(sizeof(ipacm_event_lan_client));
 				if(lan_client == NULL)
 				{
 					IPACMERR("Failed to allocate memory.\n");
-					return;
+					return IPACM_FAILURE;
 				}
 				memset(lan_client, 0, sizeof(ipacm_event_lan_client));
 				lan_client->iptype = IPA_IP_v4;
@@ -3144,31 +3191,35 @@
 				IPACM_EvtDispatcher::PostEvt(&evt_data);
 			}
 
-			for (j = 0; j < get_client_memptr(eth_client, i)->ipv6_set; j++)
+			if((get_client_memptr(eth_client, i)->ipv6_set > 0)
+				&& (iptype == IPA_IP_v6))
 			{
-				lan_client = (ipacm_event_lan_client*)malloc(sizeof(ipacm_event_lan_client));
-				if(lan_client == NULL)
+				for (j = 0; j < get_client_memptr(eth_client, i)->ipv6_set; j++)
 				{
-					IPACMERR("Failed to allocate memory.\n");
-					return;
+					lan_client = (ipacm_event_lan_client*)malloc(sizeof(ipacm_event_lan_client));
+					if(lan_client == NULL)
+					{
+						IPACMERR("Failed to allocate memory.\n");
+						return IPACM_FAILURE;
+					}
+					memset(lan_client, 0, sizeof(ipacm_event_lan_client));
+					lan_client->iptype = IPA_IP_v6;
+					lan_client->ipv6_addr[0] = get_client_memptr(eth_client, i)->v6_addr[j][0];
+					lan_client->ipv6_addr[0] = get_client_memptr(eth_client, i)->v6_addr[j][0];
+					lan_client->ipv6_addr[0] = get_client_memptr(eth_client, i)->v6_addr[j][0];
+					lan_client->ipv6_addr[0] = get_client_memptr(eth_client, i)->v6_addr[j][0];
+					lan_client->p_iface = this;
+
+					memset(&evt_data, 0, sizeof(ipacm_cmd_q_data));
+					evt_data.evt_data = (void*)lan_client;
+					evt_data.event = IPA_LAN_CLIENT_DISCONNECT;
+
+					IPACMDBG("Posting event IPA_LAN_CLIENT_DISCONNECT\n");
+					IPACM_EvtDispatcher::PostEvt(&evt_data);
 				}
-				memset(lan_client, 0, sizeof(ipacm_event_lan_client));
-				lan_client->iptype = IPA_IP_v6;
-				lan_client->ipv6_addr[0] = get_client_memptr(eth_client, i)->v6_addr[j][0];
-				lan_client->ipv6_addr[0] = get_client_memptr(eth_client, i)->v6_addr[j][0];
-				lan_client->ipv6_addr[0] = get_client_memptr(eth_client, i)->v6_addr[j][0];
-				lan_client->ipv6_addr[0] = get_client_memptr(eth_client, i)->v6_addr[j][0];
-				lan_client->p_iface = this;
-
-				memset(&evt_data, 0, sizeof(ipacm_cmd_q_data));
-				evt_data.evt_data = (void*)lan_client;
-				evt_data.event = IPA_LAN_CLIENT_DISCONNECT;
-
-				IPACMDBG("Posting event IPA_LAN_CLIENT_DISCONNECT\n");
-				IPACM_EvtDispatcher::PostEvt(&evt_data);
 			}
 	} /* end of for loop */
-	return;
+	return IPACM_SUCCESS;
 }
 
 void IPACM_Lan::install_tcp_ctl_flt_rule(ipa_ip_type iptype)
diff --git a/ipacm/src/IPACM_Main.cpp b/ipacm/src/IPACM_Main.cpp
index 8871303..d474d73 100644
--- a/ipacm/src/IPACM_Main.cpp
+++ b/ipacm/src/IPACM_Main.cpp
@@ -199,7 +199,7 @@
 		if(event == NULL)
 		{
 			IPACMERR("Failed to allocate memory.\n");
-			return;
+			return NULL;
 		}
 		memset(event, 0, length);
 		memcpy(event, buffer, length);
diff --git a/ipacm/src/IPACM_Netlink.cpp b/ipacm/src/IPACM_Netlink.cpp
index d579952..9c616af 100644
--- a/ipacm/src/IPACM_Netlink.cpp
+++ b/ipacm/src/IPACM_Netlink.cpp
@@ -210,6 +210,11 @@
 
 	while(true)
 	{
+	    for(i = 0; i < sk_fd_set->num_fd; i++ )
+		{
+			FD_SET(sk_fd_set->sk_fds[i].sk_fd, &(sk_fd_set->fdset));
+		}
+
 		if((ret = select(sk_fd_set->max_fd + 1, &(sk_fd_set->fdset), NULL, NULL, NULL)) < 0)
 		{
 			IPACMERR("ipa_nl select failed\n");
@@ -230,6 +235,7 @@
 											 i,
 											 sk_fd_set->sk_fds[i].sk_fd);
 						}
+						FD_CLR(sk_fd_set->sk_fds[i].sk_fd, &(sk_fd_set->fdset));
 					}
 					else
 					{
@@ -1595,6 +1601,7 @@
 	if(ipa_nl_addfd_map(sk_fdset, sk_info.sk_fd, read_f) != IPACM_SUCCESS)
 	{
 		IPACMERR("cannot add nl routing sock for reading\n");
+		close(sk_info.sk_fd);
 		return IPACM_FAILURE;
 	}
 
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
index 3ec5fab..2c02e31 100644
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.cpp
@@ -416,6 +416,43 @@
 				  	handle_route_add_evt(data->iptype);
 				}
 			}
+			else /* double check if current default iface is not itself */
+			{
+				if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == true))
+				{
+					IPACMDBG("Received v4 IPA_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
+					IPACMDBG("ipv4 addr 0x%x\n", data->ipv4_addr);
+					IPACMDBG("ipv4 addr mask 0x%x\n", data->ipv4_addr_mask);
+					IPACMDBG("need clean default v4 route (dst:0.0.0.0) for old iface (%s)\n", dev_name);
+					if(m_is_sta_mode == Q6_WAN)
+					{
+						del_wan_firewall_rule(IPA_IP_v4);
+						install_wan_filtering_rule();
+						handle_route_del_evt_ex(IPA_IP_v4);
+					}
+					else
+					{
+						del_dft_firewall_rules(IPA_IP_v4);
+						handle_route_del_evt(IPA_IP_v4);
+					}
+				}
+				else if ((data->iptype == IPA_IP_v6) && (!data->ipv6_addr[0]) && (!data->ipv6_addr[1]) && (!data->ipv6_addr[2]) && (!data->ipv6_addr[3]) && (active_v6 == true))
+				{
+				    IPACMDBG("Received v6 IPA_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
+					IPACMDBG("need clean default v6 route for old iface (%s)\n", dev_name);
+					if(m_is_sta_mode == Q6_WAN)
+					{
+						del_wan_firewall_rule(IPA_IP_v6);
+						install_wan_filtering_rule();
+						handle_route_del_evt_ex(IPA_IP_v6);
+					}
+					else
+					{
+						del_dft_firewall_rules(IPA_IP_v6);
+						handle_route_del_evt(IPA_IP_v6);
+					}
+				}
+			}
 		}
 		break;
 
@@ -589,6 +626,11 @@
 			return IPACM_SUCCESS;
 		}
 	}
+	else
+	{
+		IPACM_Wan::backhaul_is_sta_mode	= false;
+		IPACMDBG("reset backhaul to LTE \n");
+	}
 
     for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
 	{
@@ -1414,6 +1456,37 @@
 			m_pFilteringTable->ip = IPA_IP_v6;
 			m_pFilteringTable->num_rules = (uint8_t)1;
 
+			/* Construct ICMP rule */
+			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
+			flt_rule_entry.at_rear = true;
+			flt_rule_entry.flt_rule_hdl = -1;
+			flt_rule_entry.status = -1;
+			flt_rule_entry.rule.retain_hdr = 1;
+			flt_rule_entry.rule.eq_attrib_type = 0;
+			flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
+			memcpy(&flt_rule_entry.rule.attrib,
+					 &rx_prop->rx[0].attrib,
+					 sizeof(struct ipa_rule_attrib));
+			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
+			flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6;
+			memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
+
+			if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
+			{
+				IPACMERR("Error Adding Filtering rules, aborting...\n");
+				free(m_pFilteringTable);
+				return IPACM_FAILURE;
+			}
+			else
+			{
+				IPACMDBG("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
+			}
+			/* copy filter hdls */
+			dft_wan_fl_hdl[2] = m_pFilteringTable->rules[0].flt_rule_hdl;
+
+			/* End of construct ICMP rule */
+
+			/* v6 default route */
 			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
 			if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v6)) //rt_tbl_wan_v6 rt_tbl_v6
 			{
@@ -1596,6 +1669,35 @@
 			} /* end of firewall ipv6 filter rule add for loop*/
             }
 
+			/* Construct ICMP rule */
+			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
+			flt_rule_entry.at_rear = true;
+			flt_rule_entry.flt_rule_hdl = -1;
+			flt_rule_entry.status = -1;
+			flt_rule_entry.rule.retain_hdr = 1;
+			flt_rule_entry.rule.eq_attrib_type = 0;
+			flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
+			memcpy(&flt_rule_entry.rule.attrib,
+					 &rx_prop->rx[0].attrib,
+					 sizeof(struct ipa_rule_attrib));
+			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
+			flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6;
+			memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
+
+			if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
+			{
+				IPACMERR("Error Adding Filtering rules, aborting...\n");
+				free(m_pFilteringTable);
+				return IPACM_FAILURE;
+			}
+			else
+			{
+				IPACMDBG("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
+			}
+			/* copy filter hdls */
+			dft_wan_fl_hdl[2] = m_pFilteringTable->rules[0].flt_rule_hdl;
+			/* End of construct ICMP rule */
+
 			/* setup default wan filter rule */
 			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
 
@@ -2420,6 +2522,7 @@
 			IPACMERR("ioctl IPA_IOC_QUERY_INTF_EXT_PROPS failed\n");
 			/* ext_prop memory will free when iface-down*/
 			free(ext_prop);
+			close(fd);
 			return ret;
 		}
 
@@ -2438,6 +2541,7 @@
 			IPACM_Wan::is_ext_prop_set = true;
 		}
 		free(ext_prop);
+		close(fd);
 	}
 	return IPACM_SUCCESS;
 }
@@ -2808,6 +2912,12 @@
 			IPACMERR("Error Deleting Filtering rules, aborting...\n");
 			return IPACM_FAILURE;
 		}
+		if (m_filtering.DeleteFilteringHdls(&dft_wan_fl_hdl[2],
+																				IPA_IP_v6, 1) == false)
+		{
+			IPACMERR("Error Deleting Filtering rules, aborting...\n");
+			return IPACM_FAILURE;
+		}
 		num_firewall_v6 = 0;
 	}
 
@@ -2902,7 +3012,12 @@
 			evt_data.event = IPA_HANDLE_WAN_DOWN;
 			evt_data.evt_data = (void *)wandown_data;
 			/* Insert IPA_HANDLE_WAN_DOWN to command queue */
-			IPACMDBG("posting IPA_HANDLE_WAN_DOWN for IPv4 \n");
+			IPACMDBG("posting IPA_HANDLE_WAN_DOWN for IPv4 (%d.%d.%d.%d) \n",
+					(unsigned char)(wandown_data->ipv4_addr),
+					(unsigned char)(wandown_data->ipv4_addr >> 8),
+					(unsigned char)(wandown_data->ipv4_addr >> 16),
+					(unsigned char)(wandown_data->ipv4_addr >> 24));
+
 			IPACM_EvtDispatcher::PostEvt(&evt_data);
 			IPACMDBG("setup wan_up/active_v4= false \n");
 			IPACM_Wan::wan_up = false;
diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp
index 2b68bc7..397b67f 100644
--- a/ipacm/src/IPACM_Wlan.cpp
+++ b/ipacm/src/IPACM_Wlan.cpp
@@ -250,35 +250,35 @@
 
 					if (IPACM_Wan::isWanUP())
 					{
+						if(data->iptype == IPA_IP_v4 || data->iptype == IPA_IP_MAX)
+						{
 						if(IPACM_Wan::backhaul_is_sta_mode == false)
 						{
-							if(data->iptype == IPA_IP_v4 || data->iptype == IPA_IP_MAX)
-							{
 								ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4);
 								IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v4);
 							}
-						}
 						else
 						{
 							IPACM_Lan::handle_wan_up(IPA_IP_v4);
 						}
 					}
+					}
 
 					if(IPACM_Wan::isWanUP_V6())
 					{
+						if((data->iptype == IPA_IP_v6 || data->iptype == IPA_IP_MAX) && num_dft_rt_v6 == 1)
+						{
 						if(IPACM_Wan::backhaul_is_sta_mode == false)
 						{
-							if(data->iptype == IPA_IP_v6 || data->iptype == IPA_IP_MAX)
-							{
 								ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6);
 								IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v6);
 							}
-						}
 						else
 						{
 							IPACM_Lan::handle_wan_up(IPA_IP_v6);
 						}
 					}
+					}
 
 					IPACMDBG("posting IPA_HANDLE_WLAN_UP:Finished checking wan_up\n");
 				}
@@ -297,19 +297,19 @@
 			return;
 		}
 		IPACMDBG("Backhaul is sta mode?%d\n", data_wan->is_sta);
+		if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
+		{
 		if(data_wan->is_sta == false)
 		{
-			if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
-			{
 				ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4);
 				IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v4);
 			}
-		}
 		else
 		{
 			IPACM_Lan::handle_wan_up(IPA_IP_v4);
 		}
 	}
+	}
 		break;
 
 	case IPA_HANDLE_WAN_UP_V6:
@@ -322,18 +322,18 @@
 			return;
 		}
 		IPACMDBG("Backhaul is sta mode?%d\n", data_wan->is_sta);
+		if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
+		{
 		if(data_wan->is_sta == false)
 		{
-			if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
-			{
 				ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6);
 				IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v6);
 			}
-		}
 		else
 		{
 			IPACM_Lan::handle_wan_up(IPA_IP_v6);
 		}
+		}
 		break;
 
 	case IPA_HANDLE_WAN_DOWN:
@@ -364,6 +364,11 @@
 			IPACMERR("No event data is found.\n");
 			return;
 		}
+		/* clean up v6 RT rules*/
+		IPACMDBG("Received IPA_WAN_V6_DOWN in WLAN-instance and need clean up client IPv6 address \n");
+		/* reset wifi-client ipv6 rt-rules */
+		handle_wlan_client_reset_rt(IPA_IP_v6);
+
 		IPACMDBG("Backhaul is sta mode?%d\n", data_wan->is_sta);
 		if(data_wan->is_sta == false && wlan_ap_index > 0)
 		{
@@ -396,7 +401,8 @@
 			{
 				IPACMDBG("Received IPA_WLAN_CLIENT_DEL_EVENT\n");
 				/* support lan2lan ipa-HW feature*/
-				handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_DISCONNECT);
+				handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_DISCONNECT, IPA_IP_v4);
+				handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_DISCONNECT, IPA_IP_v6);
 				handle_wlan_client_down_evt(data->mac_addr);
 			}
 		}
@@ -410,7 +416,8 @@
 			{
 				IPACMDBG("Received IPA_WLAN_CLIENT_POWER_SAVE_EVENT\n");
 				/* support lan2lan ipa-HW feature*/
-				handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_POWER_SAVE);
+				handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_POWER_SAVE, IPA_IP_v4);
+				handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_POWER_SAVE, IPA_IP_v6);
 				handle_wlan_client_pwrsave(data->mac_addr);
 			}
 		}
@@ -424,7 +431,8 @@
 			{
 				IPACMDBG("Received IPA_WLAN_CLIENT_RECOVER_EVENT\n");
 				/* support lan2lan ipa-HW feature*/
-				handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_POWER_RECOVER);
+				handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_POWER_RECOVER, IPA_IP_v4);
+				handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_POWER_RECOVER, IPA_IP_v6);
 
 				wlan_index = get_wlan_client_index(data->mac_addr);
 				if ((wlan_index != IPACM_INVALID_INDEX) &&
@@ -895,6 +903,10 @@
 			private_fl_rule_hdl[i] = pFilteringTable->rules[i].rule_hdl;
 		}
 	}
+	else
+	{
+		return IPACM_SUCCESS;
+	}
 fail:
 	free(pFilteringTable);
 	return res;
@@ -955,6 +967,7 @@
 	if (pFilteringTable == NULL)
 	{
 		IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
+		close(fd);
 		return IPACM_FAILURE;
 	}
 	memset(pFilteringTable, 0, len);
@@ -1312,23 +1325,26 @@
 				break;
 			}
 		}
-	}
 
-	/* initialize wifi client*/
-	get_client_memptr(wlan_client, num_wifi_client)->route_rule_set_v4 = false;
-    get_client_memptr(wlan_client, num_wifi_client)->route_rule_set_v6 = 0;
-	get_client_memptr(wlan_client, num_wifi_client)->ipv4_set = false;
-    get_client_memptr(wlan_client, num_wifi_client)->ipv6_set = 0;
-    get_client_memptr(wlan_client, num_wifi_client)->power_save_set=false;
-	num_wifi_client++;
-	header_name_count++; //keep increasing header_name_count
-	IPACM_Wlan::total_num_wifi_clients++;
-	res = IPACM_SUCCESS;
-	IPACMDBG("Wifi client number: %d\n", num_wifi_client);
+		/* initialize wifi client*/
+		get_client_memptr(wlan_client, num_wifi_client)->route_rule_set_v4 = false;
+		get_client_memptr(wlan_client, num_wifi_client)->route_rule_set_v6 = 0;
+		get_client_memptr(wlan_client, num_wifi_client)->ipv4_set = false;
+		get_client_memptr(wlan_client, num_wifi_client)->ipv6_set = 0;
+		get_client_memptr(wlan_client, num_wifi_client)->power_save_set=false;
+		num_wifi_client++;
+		header_name_count++; //keep increasing header_name_count
+		IPACM_Wlan::total_num_wifi_clients++;
+		res = IPACM_SUCCESS;
+		IPACMDBG("Wifi client number: %d\n", num_wifi_client);
+	}
+	else
+	{
+		return res;
+	}
 
 fail:
 	free(pHeaderDescriptor);
-
 	return res;
 }
 
@@ -1971,7 +1987,8 @@
 
 		IPACMDBG("Delete %d client header\n", num_wifi_client);
 
-		handle_lan2lan_msg_post(get_client_memptr(wlan_client, i)->mac, IPA_LAN_CLIENT_DISCONNECT);
+		handle_lan2lan_msg_post(get_client_memptr(wlan_client, i)->mac, IPA_LAN_CLIENT_DISCONNECT, IPA_IP_v4);
+		handle_lan2lan_msg_post(get_client_memptr(wlan_client, i)->mac, IPA_LAN_CLIENT_DISCONNECT, IPA_IP_v6);
 
         if(get_client_memptr(wlan_client, i)->ipv4_header_set == true)
         {
@@ -2039,8 +2056,45 @@
 	return res;
 }
 
+/*handle reset wifi-client rt-rules */
+int IPACM_Wlan::handle_wlan_client_reset_rt(ipa_ip_type iptype)
+{
+	int i, res = IPACM_SUCCESS;
+
+	/* clean wifi-client routing rules */
+	IPACMDBG("left %d wifi clients to reset ip-type(%d) rules \n ", num_wifi_client, iptype);
+
+	for (i = 0; i < num_wifi_client; i++)
+	{
+		/* Reset RT rules */
+		res = delete_default_qos_rtrules(i, iptype);
+		if (res != IPACM_SUCCESS)
+		{
+			IPACMERR("Failed to delete old iptype(%d) rules.\n", iptype);
+			return res;
+		}
+		/* Pass info to LAN2LAN module */
+		res = handle_lan2lan_msg_post(get_client_memptr(wlan_client, i)->mac, IPA_LAN_CLIENT_DISCONNECT, iptype);
+		if (res != IPACM_SUCCESS)
+		{
+			IPACMERR("Failed to posting delete old iptype(%d) address.\n", iptype);
+			return res;
+		}
+		/* Reset ip-address */
+		if(iptype == IPA_IP_v4)
+		{
+			get_client_memptr(wlan_client, i)->ipv4_set = false;
+		}
+		else
+		{
+			get_client_memptr(wlan_client, i)->ipv6_set = 0;
+		}
+	} /* end of for loop */
+	return res;
+}
+
 /*handle lan2lan internal mesg posting*/
-int IPACM_Wlan::handle_lan2lan_msg_post(uint8_t *mac_addr, ipa_cm_event_id event)
+int IPACM_Wlan::handle_lan2lan_msg_post(uint8_t *mac_addr, ipa_cm_event_id event,ipa_ip_type iptype)
 {
 	int client_index;
 	client_index = get_wlan_client_index(mac_addr);
@@ -2052,7 +2106,8 @@
 
 	ipacm_event_lan_client* lan_client;
 	ipacm_cmd_q_data evt_data;
-	if(get_client_memptr(wlan_client, client_index)->ipv4_set == true) /* handle ipv4 case*/
+	if((get_client_memptr(wlan_client, client_index)->ipv4_set == true)
+		&& (iptype == IPA_IP_v4)) /* handle ipv4 case*/
 	{
 		if(ip_type != IPA_IP_v4 && ip_type != IPA_IP_MAX)
 		{
@@ -2080,7 +2135,8 @@
 		IPACM_EvtDispatcher::PostEvt(&evt_data);
 	}
 
-	if(get_client_memptr(wlan_client, client_index)->ipv6_set > 0) /* handle v6 case: may be multiple v6 addr */
+	if((get_client_memptr(wlan_client, client_index)->ipv6_set > 0)
+		&& (iptype == IPA_IP_v6)) /* handle v6 case: may be multiple v6 addr */
 	{
 		if(ip_type != IPA_IP_v6 && ip_type != IPA_IP_MAX)
 		{
@@ -2624,6 +2680,7 @@
 	return;
 }
 
+/* install TCP control filter rules */
 void IPACM_Wlan::install_tcp_ctl_flt_rule(ipa_ip_type iptype)
 {
 	if (rx_prop == NULL)
@@ -2796,4 +2853,4 @@
 		}
 	}
 	return IPACM_SUCCESS;
-}
\ No newline at end of file
+}
diff --git a/ipanat/src/Android.mk b/ipanat/src/Android.mk
new file mode 100644
index 0000000..a1116df
--- /dev/null
+++ b/ipanat/src/Android.mk
@@ -0,0 +1,24 @@
+ifneq (,$(filter $(QCOM_BOARD_PLATFORMS),$(TARGET_BOARD_PLATFORM)))
+ifneq (, $(filter aarch64 arm arm64, $(TARGET_ARCH)))
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/../inc
+LOCAL_C_INCLUDES += $(LOCAL_PATH)
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+
+LOCAL_SRC_FILES := ipa_nat_drv.c \
+                   ipa_nat_drvi.c
+
+LOCAL_CFLAGS := -DDEBUG
+LOCAL_MODULE := libipanat
+LOCAL_MODULE_TAGS := debug
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif # $(TARGET_ARCH)
+endif