Merge "1.	Only interfaces that register rx or tx properties should be nat by ipahw 2.      Change NAT-logic in IPACM to only do NATTING for NAT-iface clients 3.      Instaed of blocking NON-NAT iface clients"
diff --git a/ipacm/inc/IPACM_Config.h b/ipacm/inc/IPACM_Config.h
old mode 100644
new mode 100755
index 27c7ff3..f114ae8
--- a/ipacm/inc/IPACM_Config.h
+++ b/ipacm/inc/IPACM_Config.h
@@ -47,8 +47,7 @@
 typedef struct
 {
   char iface_name[IPA_IFACE_NAME_LEN];
-	uint32_t ipv4_addr;
-}NonNatIfaces;
+}NatIfaces;
 
 /* for IPACM rm dependency use*/
 typedef struct _ipa_rm_client
@@ -87,7 +86,7 @@
 	ipa_private_subnet private_subnet_table[IPA_MAX_PRIVATE_SUBNET_ENTRIES];
 
 	/* Store the non nat iface names */
-	NonNatIfaces *pNonNatIfaces; 
+	NatIfaces *pNatIfaces; 
 
 	/* Store the number of interface IPACM read from XML file */
 	int ipa_num_ipa_interfaces;
@@ -98,7 +97,7 @@
 
 	int ipa_nat_max_entries;
 
-	int ipa_non_nat_iface_entries;
+	int ipa_nat_iface_entries;
 
 	/* IPACM routing table name for v4/v6 */
 	struct ipa_ioc_get_rt_tbl rt_tbl_lan_v4, rt_tbl_wan_v4, rt_tbl_default_v4, rt_tbl_v6, rt_tbl_wan_v6;
@@ -118,17 +117,21 @@
 		return ipa_nat_max_entries;
 	}
 
-	inline int GetNonNatIfacesCnt()
+	inline int GetNatIfacesCnt()
 	{
-		return ipa_non_nat_iface_entries;
+		return ipa_nat_iface_entries;
 	}
-	int GetNonNatIfaces(int nPorts, NonNatIfaces *ifaces);
+	int GetNatIfaces(int nPorts, NatIfaces *ifaces);
 
 	/* for IPACM resource manager dependency usage */
 	void AddRmDepend(ipa_rm_resource_name rm1,bool rx_bypass_ipa);
  
 	void DelRmDepend(ipa_rm_resource_name rm1);
 	
+	int AddNatIfaces(char *dev_name);
+
+	int DelNatIfaces(char *dev_name);
+	
 private:
 	static IPACM_Config *pInstance;
 	IPACM_Config(void);
diff --git a/ipacm/inc/IPACM_ConntrackListener.h b/ipacm/inc/IPACM_ConntrackListener.h
old mode 100644
new mode 100755
index 7b9ebf4..dac3ea8
--- a/ipacm/inc/IPACM_ConntrackListener.h
+++ b/ipacm/inc/IPACM_ConntrackListener.h
@@ -43,6 +43,8 @@
 #include "IPACM_Conntrack_NATApp.h"
 #include "IPACM_Listener.h"
 
+#define MAX_NAT_IFACES 50
+
 using namespace std;
 
 class IPACM_ConntrackListener : public IPACM_Listener
@@ -52,8 +54,9 @@
 	 bool isCTReg;
 	 bool isWanUp;
 
-	 int NonNatIfaceCnt;
-	 NonNatIfaces *pNonNatIfaces;
+	 int NatIfaceCnt;
+	 NatIfaces *pNatIfaces;
+	 uint32_t nat_iface_ipv4_addr[MAX_NAT_IFACES];
 	 IPACM_Config *pConfig;
 	 
 	 void ProcessCTMessage(void *data);
diff --git a/ipacm/inc/IPACM_Xml.h b/ipacm/inc/IPACM_Xml.h
old mode 100644
new mode 100755
index 9007bfc..4b10266
--- a/ipacm/inc/IPACM_Xml.h
+++ b/ipacm/inc/IPACM_Xml.h
@@ -164,10 +164,6 @@
 #define IPACMNat_TAG                         "IPACMNAT"
 #define NAT_MaxEntries_TAG                   "MaxNatEntries"
 
-#define IPACMNonNatIfaces_TAG                "IPACMNONNATIFACES"
-#define IfaceName_TAG                        "IfaceName"
-
-
 /*---------------------------------------------------------------------------
       IP protocol numbers - use in dss_socket() to identify protocols.
       Also contains the extension header types for IPv6.
@@ -262,7 +258,6 @@
   ipacm_private_subnet_conf_t private_subnet_config;
   ipacm_alg_conf_t alg_config;
 	int nat_max_entries;
-	ipacm_iface_conf_t non_nat_ifaces;
 } IPACM_conf_t;  
 
 /* This function read IPACM XML configuration*/
diff --git a/ipacm/src/IPACM_Config.cpp b/ipacm/src/IPACM_Config.cpp
old mode 100644
new mode 100755
index ae658b2..4717db0
--- a/ipacm/src/IPACM_Config.cpp
+++ b/ipacm/src/IPACM_Config.cpp
@@ -58,6 +58,7 @@
 	ipa_num_private_subnet = 0;
 	ipa_num_alg_ports = 0;
 	ipa_nat_max_entries = 0;
+	ipa_nat_iface_entries = 0;
 
 	memset(&rt_tbl_default_v4, 0, sizeof(rt_tbl_default_v4));
 	memset(&rt_tbl_lan_v4, 0, sizeof(rt_tbl_lan_v4));
@@ -143,20 +144,13 @@
 	ipa_nat_max_entries = cfg->nat_max_entries;
 	IPACMDBG("Nat Maximum Entries %d\n", ipa_nat_max_entries);
 
-	ipa_non_nat_iface_entries = cfg->non_nat_ifaces.num_iface_entries;
-	IPACMDBG("Number of Non Nat Iface Entries %d\n", ipa_non_nat_iface_entries);
-
-	pNonNatIfaces = (NonNatIfaces *)calloc(ipa_non_nat_iface_entries,
-																					sizeof(NonNatIfaces));
-	if (pNonNatIfaces != NULL)
+	/* Allocate more non-nat entries if the monitored iface dun have Tx/Rx properties */
+	pNatIfaces = (NatIfaces *)calloc(ipa_num_ipa_interfaces, sizeof(NatIfaces));
+	if (pNatIfaces == NULL)
 	{
-		for (i=0; i<cfg->non_nat_ifaces.num_iface_entries; i++)
-		{
-			memcpy(pNonNatIfaces[i].iface_name, 
-						 cfg->non_nat_ifaces.iface_entries[i].iface_name, 
-						 sizeof(pNonNatIfaces[i].iface_name));
-			IPACMDBG("IPACM_Config::pNonNatIfaces[%d] = %s\n", i, pNonNatIfaces[i].iface_name);
-		}
+		IPACMERR("unable to allocate nat ifaces\n");
+		ret = IPACM_FAILURE;
+		goto fail;
 	}
 
 	/* Construct the routing table ictol name in iface static member*/
@@ -252,7 +246,7 @@
 	return 0;
 }
 
-int IPACM_Config::GetNonNatIfaces(int nIfaces, NonNatIfaces *pIfaces)
+int IPACM_Config::GetNatIfaces(int nIfaces, NatIfaces *pIfaces)
 {
 	if (nIfaces <= 0 || pIfaces == NULL)
 	{
@@ -263,13 +257,68 @@
 	for (int cnt=0; cnt<nIfaces; cnt++)
 	{
 		memcpy(pIfaces[cnt].iface_name, 
-					 pNonNatIfaces[cnt].iface_name, 
+					 pNatIfaces[cnt].iface_name, 
 					 sizeof(pIfaces[cnt].iface_name));
 	}
 
 	return 0;
 }
 
+
+int IPACM_Config::AddNatIfaces(char *dev_name)
+{
+	IPACMDBG("Add iface %s to NAT-ifaces, origin it has %d nat ifaces\n", 
+					          dev_name, ipa_nat_iface_entries);
+	ipa_nat_iface_entries++;
+
+	if (ipa_nat_iface_entries < ipa_num_ipa_interfaces)
+	{
+		memcpy(pNatIfaces[ipa_nat_iface_entries - 1].iface_name,
+					 dev_name, IPA_IFACE_NAME_LEN);
+
+		IPACMDBG("Add Nat IfaceName: %s ,update nat-ifaces number: %d\n",
+						 pNatIfaces[ipa_nat_iface_entries - 1].iface_name, 
+						 ipa_nat_iface_entries);
+	}
+	
+	return 0;
+}
+
+int IPACM_Config::DelNatIfaces(char *dev_name)
+{
+	int i = 0;
+	IPACMDBG("Del iface %s from NAT-ifaces, origin it has %d nat ifaces\n",
+					 dev_name, ipa_nat_iface_entries);
+
+	for (i = 0; i < ipa_nat_iface_entries; i++)
+	{
+		if (strcmp(dev_name, pNatIfaces[i].iface_name) == 0)
+		{
+			IPACMDBG("Find Nat IfaceName: %s ,previous nat-ifaces number: %d\n",
+							 pNatIfaces[i].iface_name, ipa_nat_iface_entries);
+
+			/* Reset the matched entry */
+			memset(pNatIfaces[i].iface_name, 0, IPA_IFACE_NAME_LEN);
+
+			for (i; i < ipa_nat_iface_entries - 1; i++)
+			{
+				memcpy(pNatIfaces[i].iface_name,
+							 pNatIfaces[i + 1].iface_name, IPA_IFACE_NAME_LEN);
+
+				/* Reset the copied entry */
+				memset(pNatIfaces[i + 1].iface_name, 0, IPA_IFACE_NAME_LEN);
+			}
+			ipa_nat_iface_entries--;
+			IPACMDBG("Update nat-ifaces number: %d\n", ipa_nat_iface_entries);
+			return 0;
+		}
+	}
+
+	IPACMDBG("Can't find Nat IfaceName: %s with total nat-ifaces number: %d\n",
+					    dev_name, ipa_nat_iface_entries);
+	return 0;
+}
+
 /* for IPACM resource manager dependency usage
    add either Tx or Rx ipa_rm_resource_name and
    also indicate that endpoint property if valid */
diff --git a/ipacm/src/IPACM_ConntrackListener.cpp b/ipacm/src/IPACM_ConntrackListener.cpp
index 5d61bc2..8d9a0e4 100755
--- a/ipacm/src/IPACM_ConntrackListener.cpp
+++ b/ipacm/src/IPACM_ConntrackListener.cpp
@@ -41,10 +41,12 @@
 	 isCTReg = false;
 	 isWanUp = false;
 
-	 NonNatIfaceCnt = 0;
-	 pNonNatIfaces = NULL;
+	 NatIfaceCnt = 0;
+	 pNatIfaces = NULL;
 	 pConfig = NULL;
 
+	 memset(nat_iface_ipv4_addr, 0, sizeof(nat_iface_ipv4_addr));
+
 	 IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, this);
 	 IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, this);
 	 IPACM_EvtDispatcher::registr(IPA_PROCESS_CT_MESSAGE, this);
@@ -136,7 +138,7 @@
 void IPACM_ConntrackListener::HandleNeighIpAddrEvt(void *in_param, bool del)
 {
 	ipacm_event_data_all *data = (ipacm_event_data_all *)in_param;
-	int fd=0, len=0;
+	int fd = 0, len = 0, cnt, i, j;
 	struct ifreq ifr;
 
 	if(del == false)
@@ -159,25 +161,34 @@
 			IPACMERR("Unable to get Config instance\n");
 			return;
 		}
+	}
 
-		NonNatIfaceCnt = pConfig->GetNonNatIfacesCnt();
-		if(NonNatIfaceCnt != 0)
+	cnt = pConfig->GetNatIfacesCnt();
+	if(NatIfaceCnt != cnt)
+	{
+		NatIfaceCnt = cnt;
+		if(pNatIfaces != NULL)
 		{
-			len = (sizeof(NonNatIfaces) * NonNatIfaceCnt);
-			pNonNatIfaces = (NonNatIfaces *)malloc(len);
-			if(pNonNatIfaces == NULL)
+			free(pNatIfaces);
+			pNatIfaces = NULL;
+		}
+
+		len = (sizeof(NatIfaces) * NatIfaceCnt);
+		pNatIfaces = (NatIfaces *)malloc(len);
+		if(pNatIfaces == NULL)
 			{
 				IPACMERR("Unable to allocate memory for non nat ifaces\n");
 				return;
 			}
-			memset(pNonNatIfaces, 0, len); 
+		memset(pNatIfaces, 0, len);
 
-			if(pConfig->GetNonNatIfaces(NonNatIfaceCnt, pNonNatIfaces) != 0)
+		if(pConfig->GetNatIfaces(NatIfaceCnt, pNatIfaces) != 0)
 			{
 				IPACMERR("Unable to retrieve non nat ifaces\n");
 				return;
 			}
-		}
+
+		IPACMDBG("Update %d Nat ifaces", NatIfaceCnt);
 	}
 
 	/* Search/Configure linux interface-index and map it to IPA interface-index */
@@ -197,34 +208,45 @@
 		return;
 	}
 
-	for (int i = 0; i <NonNatIfaceCnt; i++)
+	for(i = 0; i < NatIfaceCnt; i++)
 	{
 		if (strncmp(ifr.ifr_name, 
-								pNonNatIfaces[i].iface_name,
-								sizeof(pNonNatIfaces[i].iface_name)) == 0)
+							 pNatIfaces[i].iface_name,
+							 sizeof(pNatIfaces[i].iface_name)) == 0)
 		{
 			/* copy the ipv4 address to filter out downlink connections
 			   ignore downlink after listening connection event from
 			   conntrack as it is not destinated to private ip address */
 
-			IPACMDBG("Interface (%s) is non nat\n", ifr.ifr_name);
+			IPACMDBG("Interface (%s) is nat\n", ifr.ifr_name);
 			if(del == false)
 			{
-				pNonNatIfaces[i].ipv4_addr = data->ipv4_addr;
-				IPACMDBG("Ignore connections of Interface (%s)\n", pNonNatIfaces[i].iface_name);
-				IPACM_ConntrackClient::iptodot("and ipv4 address", pNonNatIfaces[i].ipv4_addr);
+				for(j = 0; j < MAX_NAT_IFACES; j++)
+				{
+					if(nat_iface_ipv4_addr[j] == 0)
+					{
+						nat_iface_ipv4_addr[j] = data->ipv4_addr;
+						break;
+					}
+				}
+				IPACMDBG("Nating connections of Interface (%s)\n", pNatIfaces[i].iface_name);
+				IPACM_ConntrackClient::iptodot("with ipv4 address", nat_iface_ipv4_addr[j]);
 			}
 			else
 			{
-				if(pNonNatIfaces[i].ipv4_addr == 0)
+				for(j = 0; j < MAX_NAT_IFACES; j++)
 				{
-					IPACMDBG("Ignoring IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, redudancy\n");
-					return;
+					if(nat_iface_ipv4_addr[j] == data->ipv4_addr)
+				{
+						/* Reset */
+						IPACMDBG("Reseting ct filters of Interface (%s)\n", pNatIfaces[i].iface_name);
+						IPACM_ConntrackClient::iptodot("with ipv4 address", nat_iface_ipv4_addr[j]);
+
+						nat_iface_ipv4_addr[j] = 0;
+						break;
+					}
 				}
 
-				/* Reset it to avoid redudancy */
-				pNonNatIfaces[i].ipv4_addr = 0;
-				IPACMDBG("Reseting ct filters of Interface (%s)\n", pNonNatIfaces[i].iface_name);
 			}
 			break;
 		}
@@ -558,18 +580,26 @@
 	 /* Retrieve Protocol */
 	 rule.protocol = nfct_get_attr_u8(ct, ATTR_REPL_L4PROTO);
 
-	 for(int cnt = 0; cnt < NonNatIfaceCnt; cnt++)
+	 int cnt;
+	 for(cnt = 0; cnt <MAX_NAT_IFACES; cnt++)
 	 {
-		 if(pNonNatIfaces[cnt].ipv4_addr != 0)
+		 if(nat_iface_ipv4_addr[cnt] != 0)
 		 {
-			 if(rule.private_ip == pNonNatIfaces[cnt].ipv4_addr ||
-					rule.target_ip == pNonNatIfaces[cnt].ipv4_addr)
+			 if(rule.private_ip == nat_iface_ipv4_addr[cnt] ||
+					rule.target_ip == nat_iface_ipv4_addr[cnt])
 			 {
-				 IPACMDBG("Non Nat iface %s match, Ignoring above Nat entry\n",
-									pNonNatIfaces[cnt].iface_name);
-				 return;
+				IPACM_ConntrackClient::iptodot("ProcessTCPorUDPMsg(): Nat entry match with ip addr", 
+				                       nat_iface_ipv4_addr[cnt]);
+				 break;
+			 }
 			 }
 		 }
+	 
+	 if(cnt == MAX_NAT_IFACES)
+	 {
+		IPACM_ConntrackClient::iptodot("ProcessTCPorUDPMsg(): ignoring iface with ip address", 
+				                       nat_iface_ipv4_addr[cnt]);
+	    return;
 	 }
 	 
 	 IPACMDBG("Nat Entry with below information will be added\n");
diff --git a/ipacm/src/IPACM_Iface.cpp b/ipacm/src/IPACM_Iface.cpp
old mode 100644
new mode 100755
index d717007..3328a01
--- a/ipacm/src/IPACM_Iface.cpp
+++ b/ipacm/src/IPACM_Iface.cpp
@@ -508,6 +508,13 @@
 		}
 	}
 
+	/* Add Natting iface to IPACM_Config if there is  Rx/Tx property */
+	if (rx_prop != NULL || tx_prop != NULL)
+	{
+		IPACMDBG(" Has rx/tx properties registered for iface %s, add for NATTING \n", dev_name);
+        IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name);
+	}		
+	
 	close(fd);
 	return res;
 }
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
old mode 100644
new mode 100755
index 37cd8de..a3e6f9a
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -88,6 +88,7 @@
 				IPACMDBG("Received IPA_LINK_DOWN_EVENT\n");
 				handle_down_evt();
 				IPACMDBG("ipa_LAN (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num);
+				IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
 				delete this;
 				return;
 			}
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
old mode 100644
new mode 100755
index f2edb55..347f5ce
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.cpp
@@ -248,6 +248,7 @@
                                 {
 	            	             IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat=UNKNOWN_IF;
                                 }
+				IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface				
 				delete this;
 				return;
 			}
diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp
old mode 100644
new mode 100755
index ac54334..615d7b9
--- a/ipacm/src/IPACM_Wlan.cpp
+++ b/ipacm/src/IPACM_Wlan.cpp
@@ -111,6 +111,7 @@
 				IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num);
 				/* reset the AP-iface category to unknown */				 
 				IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat=UNKNOWN_IF;
+				IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
 				delete this;
 				return;
 			}
diff --git a/ipacm/src/IPACM_Xml.cpp b/ipacm/src/IPACM_Xml.cpp
old mode 100644
new mode 100755
index 38ec035..9f07ebe
--- a/ipacm/src/IPACM_Xml.cpp
+++ b/ipacm/src/IPACM_Xml.cpp
@@ -182,9 +182,7 @@
 						IPACM_util_icmp_string((char*)xml_node->name,
 																	 ALG_TAG) == 0 ||
 						IPACM_util_icmp_string((char*)xml_node->name,
-																	 IPACMNat_TAG) == 0 ||
-						IPACM_util_icmp_string((char*)xml_node->name,
-																	 IPACMNonNatIfaces_TAG) == 0)
+																	 IPACMNat_TAG) == 0)
 				{
 					if (0 == IPACM_util_icmp_string((char*)xml_node->name,
 																					IFACE_TAG))
@@ -336,24 +334,6 @@
 						IPACMDBG("Nat Table Max Entries %d\n", config->nat_max_entries);
 					}
 				}
-				else if (IPACM_util_icmp_string((char*)xml_node->name,
-																				IfaceName_TAG) == 0)
-				{
-					config->non_nat_ifaces.num_iface_entries++;
-					content = IPACM_read_content_element(xml_node);
-					if (content)
-					{
-						str_size = strlen(content);
-						memset(content_buf, 0, sizeof(content_buf));
-
-						memcpy(content_buf, (void *)content, str_size);
-						strncpy(config->non_nat_ifaces.iface_entries[config->non_nat_ifaces.num_iface_entries - 1].iface_name, 
-										content_buf, str_size);
-
-						IPACMDBG("Non Nat IfaceName %s\n", 
-										   config->non_nat_ifaces.iface_entries[config->non_nat_ifaces.num_iface_entries - 1].iface_name);
-					}
-				}
 			}
 			break;
 		default:
diff --git a/ipacm/src/IPACM_cfg.xml b/ipacm/src/IPACM_cfg.xml
old mode 100644
new mode 100755
index 0668e28..f233dd9
--- a/ipacm/src/IPACM_cfg.xml
+++ b/ipacm/src/IPACM_cfg.xml
@@ -62,8 +62,5 @@
 		<IPACMNAT>		
  	        <MaxNatEntries>100</MaxNatEntries>
 		</IPACMNAT>
-		<IPACMNONNATIFACES>
-		    <IfaceName>rndis0</IfaceName>
-		</IPACMNONNATIFACES>
-	</IPACM>
+		</IPACM>
 </system>