Merge "(1) Support QCMAP feature: Guest_AP can.t talk to Primary_AP etc (2) Solution is to put all LAN traffic to A5"
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
index 0d9f001..7bb6cad 100644
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -212,6 +212,11 @@
                                 ipacm_event_data_addr *data2;				
 				data2 = (ipacm_event_data_addr *)
 							 malloc(sizeof(ipacm_event_data_addr));				
+				if (data2 == NULL)
+				{
+							IPACMERR("Unable to allocate memory\n");
+							return;
+				}
 				memset(data2, 0, sizeof(data2));
 				data2->iptype = IPA_IP_v4;
                                 data2->ipv4_addr = data->ipv4_addr;
@@ -240,6 +245,11 @@
                                 ipacm_event_data_addr *data2;				
 				data2 = (ipacm_event_data_addr *)
 							 malloc(sizeof(ipacm_event_data_addr));				
+				if (data2 == NULL)
+				{
+							IPACMERR("Unable to allocate memory\n");
+							return;
+				}
 				memset(data2, 0, sizeof(data2));
 				data2->iptype = IPA_IP_v4;
                                 data2->ipv4_addr = data->ipv4_addr;
@@ -358,26 +368,10 @@
 
 		           strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name);
 				   
-		       	   if (tx_prop->tx[tx_index].hdr_name)
-		       	   {
-		       	   	memset(&sRetHeader, 0, sizeof(sRetHeader));
-		       	   	strncpy(sRetHeader.name,
-		       	   					tx_prop->tx[tx_index].hdr_name,
-		       	   					sizeof(tx_prop->tx[tx_index].hdr_name));
-                   
-		       	   	if (false == m_header.GetHeaderHandle(&sRetHeader))
-		       	   	{
-		       	   		IPACMERR(" ioctl failed\n");
-		       	   	    free(rt_rule);
-		       	   	    return IPACM_FAILURE;
-		       	   	}
-                   
-		       	   	rt_rule_entry->rule.hdr_hdl = sRetHeader.hdl;
-		       	   }
-		       	   rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
-		       	   memcpy(&rt_rule_entry->rule.attrib,
-		       	   			 &tx_prop->tx[tx_index].attrib,
-		       	   			 sizeof(rt_rule_entry->rule.attrib));
+		           /* Support QCMAP LAN traffic feature, send to A5 */
+                           rt_rule_entry->rule.dst = IPA_CLIENT_A5_LAN_WAN_CONS;
+				   memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib));
+				   rt_rule_entry->rule.hdr_hdl = 0;
 		       	   rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
 		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0];
 		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1];
@@ -398,8 +392,40 @@
 		       		  = rt_rule_entry->rt_rule_hdl;
 		       	   IPACMDBG("ipv6 rt rule hdl1 for LAN-table=0x%x, entry:0x%x\n", rt_rule_entry->rt_rule_hdl,get_rt_ruleptr(route_rule, num_uni_rt)->rt_rule_hdl[tx_index]);
 
-			       /* Construct same v6 rule for rt_tbl_wan_v6*/
-				   strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name);
+			       /* Construct same v6 rule for rt_tbl_wan_v6              */
+		       	   if (tx_prop->tx[tx_index].hdr_name)
+		       	   {
+		       	   	memset(&sRetHeader, 0, sizeof(sRetHeader));
+		       	   	strncpy(sRetHeader.name,
+		       	   					tx_prop->tx[tx_index].hdr_name,
+		       	   					sizeof(tx_prop->tx[tx_index].hdr_name));
+                   
+		       	   	if (false == m_header.GetHeaderHandle(&sRetHeader))
+		       	   	{
+		       	   		IPACMERR(" ioctl failed\n");
+		       	   	    free(rt_rule);
+		       	   	    return IPACM_FAILURE;
+		       	   	}
+                   
+		       	   	rt_rule_entry->rule.hdr_hdl = sRetHeader.hdl;
+		       	   }
+
+		           /* Downlink traffic from Wan iface, directly through IPA */
+		       	   rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
+		       	   memcpy(&rt_rule_entry->rule.attrib,
+		       	   			 &tx_prop->tx[tx_index].attrib,
+		       	   			 sizeof(rt_rule_entry->rule.attrib));
+		       	   rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
+		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0];
+		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1];
+		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2];
+		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = data->ipv6_addr[3];
+		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
+		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
+		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
+		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
+		       	   
+		           strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name);
 		       	   if (false == m_routing.AddRoutingRule(rt_rule))
 		       	   {
 		       	   	IPACMERR("Routing rule addition failed!\n");
@@ -1113,13 +1139,15 @@
 			free(m_pFilteringTable);
 			return IPACM_FAILURE;
 		}
-                /* private traffic use default RT-table go A5 */
+
+		/* Make LAN-traffic always go A5, use default IPA-RT table */
 		if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4))
 		{
 			IPACMERR("LAN m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_default_v4);
 			free(m_pFilteringTable);
 			return IPACM_FAILURE;
 		}
+		
 		for (i = 0; i < (IPACM_Iface::ipacmcfg->ipa_num_private_subnet); i++)
 		{
 			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
@@ -1127,7 +1155,6 @@
 			flt_rule_entry.flt_rule_hdl = -1;
 			flt_rule_entry.status = -1;
 			flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
 
                         /* Support priave subnet feature including guest-AP can't talk to primary AP etc */
 			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl;
diff --git a/ipacm/src/IPACM_Neighbor.cpp b/ipacm/src/IPACM_Neighbor.cpp
index ed3be96..24ff567 100644
--- a/ipacm/src/IPACM_Neighbor.cpp
+++ b/ipacm/src/IPACM_Neighbor.cpp
@@ -86,6 +86,11 @@
 						    evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
 						
 	                                        data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
+				                if (data_all == NULL)
+				                {
+				        	    IPACMERR("Unable to allocate memory\n");
+				        	    return;
+				                }
 	                                        memcpy(data_all, data, sizeof(ipacm_event_data_all));
 						evt_data.evt_data = (void *)data_all;
 						IPACM_EvtDispatcher::PostEvt(&evt_data);
@@ -110,6 +115,11 @@
 					evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
 
 	                        data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
+				if (data_all == NULL)
+				{
+					IPACMERR("Unable to allocate memory\n");
+					return;
+				}
 	                        memcpy(data_all, data, sizeof(ipacm_event_data_all));
 	                        evt_data.evt_data = (void *)data_all;
 				IPACM_EvtDispatcher::PostEvt(&evt_data);
@@ -139,6 +149,11 @@
 						else evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
 						
 	                                        data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
+				                if (data_all == NULL)
+				                {
+				        	     IPACMERR("Unable to allocate memory\n");
+				        	     return;
+				                }
 	                                        memcpy(data_all, data, sizeof(ipacm_event_data_all));
 						evt_data.evt_data = (void *)data_all;
 						IPACM_EvtDispatcher::PostEvt(&evt_data);
@@ -163,6 +178,11 @@
 					evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
 
 	                        data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
+				if (data_all == NULL)
+				{
+					IPACMERR("Unable to allocate memory\n");
+					return;
+				}
 	                        memcpy(data_all, data, sizeof(ipacm_event_data_all));
 			        evt_data.evt_data = (void *)data_all;
 				IPACM_EvtDispatcher::PostEvt(&evt_data);
diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp
index e1d4c94..ac54334 100644
--- a/ipacm/src/IPACM_Wlan.cpp
+++ b/ipacm/src/IPACM_Wlan.cpp
@@ -707,6 +707,20 @@
 	                rt_rule->num_rules = (uint8_t)NUM;
 		        rt_rule->ip = iptype;
 
+
+		for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
+  	        {
+
+		        if(iptype != tx_prop->tx[tx_index].ip)
+		        {
+		   	        IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n", 
+		   	  				    tx_index, tx_prop->tx[tx_index].ip,iptype);		
+		   	        continue;
+		        }	   
+			
+  	   	        rt_rule_entry = &rt_rule->rules[0];
+			rt_rule_entry->at_rear = 0;
+
 			if (iptype == IPA_IP_v4)
 			{
 		                IPACMDBG("client index(%d):ipv4 address: 0x%x\n", wlan_index, 
@@ -718,38 +732,13 @@
 				strncpy(rt_rule->rt_tbl_name,
 								IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name,
 								sizeof(rt_rule->rt_tbl_name));
-			}
-			else
-			{
-                                IPACMDBG("client(%d): v6 header handle:(0x%x)\n",
-		  				 wlan_index,
-		  				 get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6);
 	   
-		  /* v6 LAN_RT_TBL */
-				strncpy(rt_rule->rt_tbl_name,
-								IPACM_Iface::ipacmcfg->rt_tbl_v6.name,
-								sizeof(rt_rule->rt_tbl_name));
-			}
 
-		   for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
-  	           {
-		        if(iptype != tx_prop->tx[tx_index].ip)
-		        {
-		   	        IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n", 
-		   	  				    tx_index, tx_prop->tx[tx_index].ip,iptype);		
-		   	        continue;
-		        }	   
-	              
-  	   	        rt_rule_entry = &rt_rule->rules[0];
-			rt_rule_entry->at_rear = 0;
-			rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
-			memcpy(&rt_rule_entry->rule.attrib,
+			        rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
+			        memcpy(&rt_rule_entry->rule.attrib,
 						 &tx_prop->tx[tx_index].attrib,
 						 sizeof(rt_rule_entry->rule.attrib));
-			rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
-
-			if (iptype == IPA_IP_v4)
-			{
+			        rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
 		   	        rt_rule_entry->rule.hdr_hdl = get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v4;
 				rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wlan_client, wlan_index)->v4_addr;
 				rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
@@ -773,7 +762,20 @@
 		   
 		            for(v6_num = get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6;v6_num < get_client_memptr(wlan_client, wlan_index)->ipv6_set;v6_num++)
 			    {
-		   	        rt_rule_entry->rule.hdr_hdl = get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6;
+                                IPACMDBG("client(%d): v6 header handle:(0x%x)\n",
+		  	    			 wlan_index,
+		  	    			 get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6);
+	            
+		                /* v6 LAN_RT_TBL */
+			    	strncpy(rt_rule->rt_tbl_name,
+			    					IPACM_Iface::ipacmcfg->rt_tbl_v6.name,
+			    					sizeof(rt_rule->rt_tbl_name));
+					
+		                /* Support QCMAP LAN traffic feature, send to A5 */
+				rt_rule_entry->rule.dst = IPA_CLIENT_A5_LAN_WAN_CONS;
+			        memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib));
+		   	        rt_rule_entry->rule.hdr_hdl = 0;
+			        rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
 		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][0];
 		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][1];
 		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][2];
@@ -799,6 +801,22 @@
   	                 					IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name,
   	                 					sizeof(rt_rule->rt_tbl_name));
    	                
+                                /* Downlink traffic from Wan iface, directly through IPA */
+				rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
+			        memcpy(&rt_rule_entry->rule.attrib,
+						 &tx_prop->tx[tx_index].attrib,
+						 sizeof(rt_rule_entry->rule.attrib));
+		   	        rt_rule_entry->rule.hdr_hdl = get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6;
+			        rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
+		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][0];
+		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][1];
+		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][2];
+		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][3];
+				rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
+				rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
+				rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
+				rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
+   	                
 		               if (false == m_routing.AddRoutingRule(rt_rule))
 		               {
 			           IPACMERR("Routing rule addition failed!\n");
@@ -1576,7 +1594,7 @@
 			free(m_pFilteringTable);
 			return IPACM_FAILURE;
 		}
-#if 1
+
                 /* Make LAN-traffic always go A5, use default IPA-RT table */
 		if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4))
 		{
@@ -1584,7 +1602,6 @@
 			free(m_pFilteringTable);
 			return IPACM_FAILURE;
 		}
-#endif
 
 		for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_private_subnet; i++)
 		{
@@ -1593,12 +1610,11 @@
 			flt_rule_entry.flt_rule_hdl = -1;
 			flt_rule_entry.status = -1;
 			flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
-#if 1
-                        /* ipv4 word-around way make ping happens*/
+
+                        /* Support priave subnet feature including guest-AP can't talk to primary AP etc */
 			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl;
 			IPACMDBG(" private filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_default_v4.name);
-#endif			
+	
 			memcpy(&flt_rule_entry.rule.attrib,
 						 &rx_prop->rx[0].attrib,
 						 sizeof(flt_rule_entry.rule.attrib));