Merge "IPACM: support 8994 private subnet change"
diff --git a/ipacm/inc/IPACM_Wan.h b/ipacm/inc/IPACM_Wan.h
index 24bc300..c677d79 100644
--- a/ipacm/inc/IPACM_Wan.h
+++ b/ipacm/inc/IPACM_Wan.h
@@ -107,6 +107,16 @@
 	bool header_partial_default_wan_v4;
 	bool header_partial_default_wan_v6;
 
+	static int num_ipv4_modem_pdn;
+
+	static int num_ipv6_modem_pdn;
+
+	int modem_ipv4_pdn_index;
+
+	int modem_ipv6_pdn_index;
+
+	bool is_default_gateway;
+
 	/* IPACM firewall Configuration file*/
 	IPACM_firewall_conf_t firewall_config;
 
diff --git a/ipacm/src/IPACM_Main.cpp b/ipacm/src/IPACM_Main.cpp
index b326c74..54d049b 100644
--- a/ipacm/src/IPACM_Main.cpp
+++ b/ipacm/src/IPACM_Main.cpp
@@ -125,7 +125,8 @@
 #define INOTIFY_EVENT_SIZE  (sizeof(struct inotify_event))
 #define INOTIFY_BUF_LEN     (INOTIFY_EVENT_SIZE + 2*sizeof(IPACM_FIREWALL_FILE_NAME))
 
-#define IPA_DRIVER_WLAN_EVENT_SIZE  (sizeof(struct ipa_wlan_msg_ex))
+#define IPA_DRIVER_WLAN_EVENT_MAX_OF_ATTRIBS  3
+#define IPA_DRIVER_WLAN_EVENT_SIZE  (sizeof(struct ipa_wlan_msg_ex)+ IPA_DRIVER_WLAN_EVENT_MAX_OF_ATTRIBS*sizeof(ipa_wlan_hdr_attrib_val))
 #define IPA_DRIVER_WLAN_META_MSG    (sizeof(struct ipa_msg_meta))
 #define IPA_DRIVER_WLAN_BUF_LEN     (IPA_DRIVER_WLAN_EVENT_SIZE + IPA_DRIVER_WLAN_META_MSG)
 
@@ -377,6 +378,11 @@
 		case WLAN_CLIENT_CONNECT_EX:
 			IPACMDBG("Received WLAN_CLIENT_CONNECT_EX\n");
 			memcpy(&event_ex_o, buffer + sizeof(struct ipa_msg_meta),sizeof(struct ipa_wlan_msg_ex));
+			if(event_ex_o.num_of_attribs > IPA_DRIVER_WLAN_EVENT_MAX_OF_ATTRIBS)
+			{
+				IPACMERR("buffer size overflow\n");
+				return NULL;
+			}
 			length = sizeof(ipa_wlan_msg_ex)+ event_ex_o.num_of_attribs * sizeof(ipa_wlan_hdr_attrib_val);
 			IPACMDBG("num_of_attribs %d, length %d\n", event_ex_o.num_of_attribs, length);
 			event_ex = (ipa_wlan_msg_ex *)malloc(length);
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
index 99f9ffd..d45bad2 100644
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.cpp
@@ -61,6 +61,9 @@
 bool IPACM_Wan::backhaul_is_sta_mode = false;
 bool IPACM_Wan::is_ext_prop_set = false;
 
+int IPACM_Wan::num_ipv4_modem_pdn = 0;
+int IPACM_Wan::num_ipv6_modem_pdn = 0;
+
 IPACM_Wan::IPACM_Wan(int iface_index, ipacm_wan_iface_type is_sta_mode) : IPACM_Iface(iface_index)
 {
 	num_firewall_v4 = 0;
@@ -87,6 +90,7 @@
 	if(m_is_sta_mode == Q6_WAN)
 	{
 		IPACMDBG("The new WAN interface is modem.\n");
+		is_default_gateway = false;
 		query_ext_prop();
 	}
 	else
@@ -202,6 +206,9 @@
 	    {
 			if(m_is_sta_mode == m_is_sta_mode)
 			{
+				modem_ipv6_pdn_index = num_ipv6_modem_pdn;
+				num_ipv6_modem_pdn++;
+				IPACMDBG("Now the number of modem ipv6 pdn is %d.\n", num_ipv6_modem_pdn);
 				init_fl_rule_ex(data->iptype);
 			}
 			else
@@ -253,6 +260,9 @@
 
 		if(m_is_sta_mode == m_is_sta_mode)
 		{
+			modem_ipv4_pdn_index = num_ipv4_modem_pdn;
+			num_ipv4_modem_pdn++;
+			IPACMDBG("Now the number of modem ipv4 pdn is %d.\n", num_ipv4_modem_pdn);
 			init_fl_rule_ex(data->iptype);
 		}
 		else
@@ -481,6 +491,12 @@
 
 		if(m_is_sta_mode == Q6_WAN)
 		{
+			if(is_default_gateway == false)
+			{
+				IPACMDBG("Interface %s is not default gw, return.\n", dev_name);
+				return;
+			}
+
 			if(ip_type == IPA_IP_v4)
 			{
 				del_wan_firewall_rule(IPA_IP_v4);
@@ -554,6 +570,9 @@
 		return IPACM_SUCCESS;
 	}
 
+	is_default_gateway = true;
+	IPACMDBG("Default route is added to iface %s.\n", dev_name);
+
 	if (m_is_sta_mode !=Q6_WAN)
 	{
 		IPACM_Wan::backhaul_is_sta_mode	= true;
@@ -2158,12 +2177,18 @@
 
 	if(iptype == IPA_IP_v4)
 	{
+		if(modem_ipv4_pdn_index == 0)	//install ipv4 default modem DL filtering rules only once
+		{
 		add_dft_filtering_rule(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4);
 	}
+	}
 	else if(iptype == IPA_IP_v6)
 	{
+		if(modem_ipv6_pdn_index == 0)	//install ipv6 default modem DL filtering rules only once
+		{
 		add_dft_filtering_rule(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6);
 	}
+	}
 	else
 	{
 		IPACMERR("IP type is not expected.\n");
@@ -2425,6 +2450,7 @@
 
 	if(iptype == IPA_IP_v4)
 	{
+		IPACM_Wan::num_v4_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4;
 		if(IPACM_FAILURE == add_icmp_alg_rules(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4))
 		{
 			IPACMERR("Failed to add ICMP and ALG port filtering rules.\n");
@@ -2443,6 +2469,7 @@
 	}
 	else if(iptype == IPA_IP_v6)
 	{
+		IPACM_Wan::num_v6_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6;
 		if(IPACM_FAILURE == add_icmp_alg_rules(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6))
 		{
 			IPACMERR("Failed to add ICMP and ALG port filtering rules.\n");
@@ -2519,6 +2546,8 @@
 		memcpy(&flt_rule_entry.rule.attrib,
 					 &rx_prop->rx[0].attrib,
 					 sizeof(flt_rule_entry.rule.attrib));
+		/* remove meta data mask since we only install default flt rules once for all modem PDN*/
+		flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA);
 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xF0000000;
 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000;
@@ -2594,6 +2623,8 @@
 		memcpy(&flt_rule_entry.rule.attrib,
 					 &rx_prop->rx[0].attrib,
 					 sizeof(flt_rule_entry.rule.attrib));
+		/* remove meta data mask since we only install default flt rules once for all modem PDN*/
+		flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA);
 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
@@ -2797,6 +2828,9 @@
 		return IPACM_SUCCESS;
 	}
 
+	is_default_gateway = false;
+	IPACMDBG("Default route is deleted to iface %s.\n", dev_name);
+
 	if (((iptype == IPA_IP_v4) && (active_v4 == true)) ||
 			((iptype == IPA_IP_v6) && (active_v6 == true)))
 	{
@@ -2914,6 +2948,9 @@
 		return IPACM_SUCCESS;
 	}
 
+	is_default_gateway = false;
+	IPACMDBG("Default route is deleted to iface %s.\n", dev_name);
+
 	if (((iptype == IPA_IP_v4) && (active_v4 == true)) ||
 		((iptype == IPA_IP_v6) && (active_v6 == true)))
 	{
@@ -3154,11 +3191,25 @@
 
 	if(ip_type == IPA_IP_v4)
 	{
+		num_ipv4_modem_pdn--;
+		IPACMDBG("Now the number of ipv4 modem pdn is %d.\n", num_ipv4_modem_pdn);
+		/* only when default gw goes down we post WAN_DOWN event*/
+		if(is_default_gateway == true)
+		{
 		IPACM_Wan::wan_up = 0;
+			del_wan_firewall_rule(IPA_IP_v4);
+			install_wan_filtering_rule();
+			handle_route_del_evt_ex(IPA_IP_v4);
+		}
+
+		/* only when the last ipv4 modem interface goes down, delete ipv4 default flt rules*/
+		if(num_ipv4_modem_pdn == 0)
+		{
+			IPACMDBG("Now the number of modem ipv4 interface is 0, delete default flt rules.\n");
 		IPACM_Wan::num_v4_flt_rule = 0;
 		memset(IPACM_Wan::flt_rule_v4, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
 		install_wan_filtering_rule();
-		handle_route_del_evt_ex(IPA_IP_v4);
+		}
 
 		if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
 		{
@@ -3169,11 +3220,25 @@
 	}
 	else if(ip_type == IPA_IP_v6)
 	{
+		num_ipv6_modem_pdn--;
+		IPACMDBG("Now the number of ipv6 modem pdn is %d.\n", num_ipv6_modem_pdn);
+		/* only when default gw goes down we post WAN_DOWN event*/
+		if(is_default_gateway == true)
+		{
 		IPACM_Wan::wan_up_v6 = 0;
+			del_wan_firewall_rule(IPA_IP_v6);
+			install_wan_filtering_rule();
+			handle_route_del_evt_ex(IPA_IP_v6);
+		}
+
+		/* only when the last ipv6 modem interface goes down, delete ipv6 default flt rules*/
+		if(num_ipv6_modem_pdn == 0)
+		{
+			IPACMDBG("Now the number of modem ipv6 interface is 0, delete default flt rules.\n");
 		IPACM_Wan::num_v6_flt_rule = 0;
 		memset(IPACM_Wan::flt_rule_v6, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
 		install_wan_filtering_rule();
-		handle_route_del_evt_ex(IPA_IP_v6);
+		}
 
 		for (i = 0; i < 2*num_dft_rt_v6; i++)
 		{
@@ -3187,17 +3252,40 @@
 	}
 	else
 	{
+		num_ipv4_modem_pdn--;
+		IPACMDBG("Now the number of ipv4 modem pdn is %d.\n", num_ipv4_modem_pdn);
+		num_ipv6_modem_pdn--;
+		IPACMDBG("Now the number of ipv6 modem pdn is %d.\n", num_ipv6_modem_pdn);
+		/* only when default gw goes down we post WAN_DOWN event*/
+		if(is_default_gateway == true)
+		{
 		IPACM_Wan::wan_up = 0;
-		IPACM_Wan::num_v4_flt_rule = 0;
-		memset(IPACM_Wan::flt_rule_v4, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
+			del_wan_firewall_rule(IPA_IP_v4);
 		handle_route_del_evt_ex(IPA_IP_v4);
 
 		IPACM_Wan::wan_up_v6 = 0;
+			del_wan_firewall_rule(IPA_IP_v6);
+			handle_route_del_evt_ex(IPA_IP_v6);
+
+			install_wan_filtering_rule();
+		}
+
+		/* only when the last ipv4 modem interface goes down, delete ipv4 default flt rules*/
+		if(num_ipv4_modem_pdn == 0)
+		{
+			IPACMDBG("Now the number of modem ipv4 interface is 0, delete default flt rules.\n");
+			IPACM_Wan::num_v4_flt_rule = 0;
+			memset(IPACM_Wan::flt_rule_v4, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
+			install_wan_filtering_rule();
+		}
+		/* only when the last ipv6 modem interface goes down, delete ipv6 default flt rules*/
+		if(num_ipv6_modem_pdn == 0)
+		{
+			IPACMDBG("Now the number of modem ipv6 interface is 0, delete default flt rules.\n");
 		IPACM_Wan::num_v6_flt_rule = 0;
 		memset(IPACM_Wan::flt_rule_v6, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
-		handle_route_del_evt_ex(IPA_IP_v6);
-
 		install_wan_filtering_rule();
+		}
 
 		if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
 		{
diff --git a/ipacm/src/IPACM_cfg.xml b/ipacm/src/IPACM_cfg.xml
index 5105097..95aad5a 100644
--- a/ipacm/src/IPACM_cfg.xml
+++ b/ipacm/src/IPACM_cfg.xml
@@ -19,6 +19,30 @@
 			   <Category>WAN</Category>
 			</Iface>			
 			<Iface>
+			   <Name>rmnet_data2</Name>
+			   <Category>WAN</Category>
+			</Iface>
+			<Iface>
+			   <Name>rmnet_data3</Name>
+			   <Category>WAN</Category>
+			</Iface>
+			<Iface>
+			   <Name>rmnet_data4</Name>
+			   <Category>WAN</Category>
+			</Iface>
+			<Iface>
+			   <Name>rmnet_data5</Name>
+			   <Category>WAN</Category>
+			</Iface>
+			<Iface>
+			   <Name>rmnet_data6</Name>
+			   <Category>WAN</Category>
+			</Iface>
+			<Iface>
+			   <Name>rmnet_data7</Name>
+			   <Category>WAN</Category>
+			</Iface>
+			<Iface>
 			   <Name>wlan0</Name>
 			   <Category>UNKNOWN</Category>
 			</Iface>