Merge "IPACM: support upstream wan iface in Android"
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index 3957d4c..b68237d 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -156,6 +156,8 @@
 	IPA_USB_LINK_UP_EVENT,                    /* 38 ipacm_event_data_fid */
 	IPA_PROCESS_CT_MESSAGE_V6,				  /* 39 ipacm_ct_evt_data */
 	IPA_PRIVATE_SUBNET_CHANGE_EVENT,		  /* 40 ipacm_event_data_fid */
+	IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT,          /* 41 ipacm_event_data_fid */
+	IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT,          /* 42 ipacm_event_data_fid */
 	IPACM_EVENT_MAX
 } ipa_cm_event_id;
 
@@ -208,7 +210,7 @@
 
 typedef struct
 {
-	ipa_ip_type iptype;
+	enum ipa_ip_type iptype;
 	uint32_t ipv4_addr;
 	uint32_t ipv6_addr[4];
 	uint8_t mac_addr[6];
@@ -217,7 +219,7 @@
 
 typedef struct
 {
-	ipa_ip_type iptype;
+	enum ipa_ip_type iptype;
 	uint32_t src_ipv4_addr;
 	uint32_t dst_ipv4_addr;
 	uint32_t src_ipv6_addr[4];
@@ -229,6 +231,13 @@
 	int if_index;
 } ipacm_event_data_fid;
 
+typedef struct _ipacm_event_data_iptype
+{
+	int if_index;
+	enum ipa_ip_type iptype;
+} ipacm_event_data_iptype;
+
+
 typedef struct _ipacm_event_data_addr
 {
 	enum ipa_ip_type iptype;
diff --git a/ipacm/inc/IPACM_Wan.h b/ipacm/inc/IPACM_Wan.h
index b60bb26..2b4cd03 100644
--- a/ipacm/inc/IPACM_Wan.h
+++ b/ipacm/inc/IPACM_Wan.h
@@ -137,7 +137,6 @@
 
 	int handle_down_evt();
 
-
 	/*handle wan-iface down event */
 	int handle_down_evt_ex();
 
diff --git a/ipacm/src/IPACM_IfaceManager.cpp b/ipacm/src/IPACM_IfaceManager.cpp
index 811f7c9..ac277ef 100644
--- a/ipacm/src/IPACM_IfaceManager.cpp
+++ b/ipacm/src/IPACM_IfaceManager.cpp
@@ -227,8 +227,13 @@
 				IPACMDBG("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
+				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) */
 				IPACM_EvtDispatcher::registr(IPA_ROUTE_ADD_EVENT, w);
 				IPACM_EvtDispatcher::registr(IPA_ROUTE_DEL_EVENT, w);
+#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);
diff --git a/ipacm/src/IPACM_Main.cpp b/ipacm/src/IPACM_Main.cpp
index 331ad96..47c5976 100644
--- a/ipacm/src/IPACM_Main.cpp
+++ b/ipacm/src/IPACM_Main.cpp
@@ -117,6 +117,8 @@
 	__stringify(IPA_USB_LINK_UP_EVENT),                    /* 38 ipacm_event_data_fid */
     __stringify(IPA_PROCESS_CT_MESSAGE_V6),			       /* 39 ipacm_ct_evt_data */
 	__stringify(IPA_PRIVATE_SUBNET_CHANGE_EVENT),		   /* 40 ipacm_event_data_fid */
+	__stringify(IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT),		   /* 41 ipacm_event_data_fid */
+	__stringify(IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT),		   /* 42 ipacm_event_data_fid */
 };
 
 #define IPA_DRIVER  "/dev/ipa"
@@ -151,7 +153,6 @@
 {
 	ipa_nl_sk_fd_set_info_t sk_fdset;
 	int ret_val = 0;
-
 	memset(&sk_fdset, 0, sizeof(ipa_nl_sk_fd_set_info_t));
 	IPACMDBG("netlink starter memset sk_fdset succeeds\n");
 	ret_val = ipa_nl_listener_init(NETLINK_ROUTE, (RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_LINK |
@@ -258,6 +259,7 @@
 	char buffer[IPA_DRIVER_WLAN_BUF_LEN];
 	struct ipa_msg_meta event_hdr;
 	struct ipa_ecm_msg event_ecm;
+	struct ipa_wan_msg event_wan;
 	struct ipa_wlan_msg_ex event_ex_o;
 	struct ipa_wlan_msg *event_wlan=NULL;
 	struct ipa_wlan_msg_ex *event_ex= NULL;
@@ -265,6 +267,7 @@
 	ipacm_cmd_q_data evt_data;
 	ipacm_event_data_mac *data = NULL;
     ipacm_event_data_fid *data_fid = NULL;
+	ipacm_event_data_iptype *data_iptype = NULL;
 	ipacm_event_data_wlan_ex *data_ex;
 
 	fd = open(IPA_DRIVER, O_RDWR);
@@ -532,6 +535,39 @@
 			evt_data.event = IPA_LINK_DOWN_EVENT;
 			evt_data.evt_data = data_fid;
 			break;
+        /* Add for 8994 Android case */
+		case WAN_UPSTREAM_ROUTE_ADD:
+			memcpy(&event_wan, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_wan_msg));
+			IPACMDBG("Received WAN_UPSTREAM_ROUTE_ADD name: %s\n",event_wan.name);
+            data_iptype = (ipacm_event_data_iptype *)malloc(sizeof(ipacm_event_data_iptype));
+			if(data_iptype == NULL)
+			{
+				IPACMERR("unable to allocate memory for event_ecm data_iptype\n");
+				return NULL;
+			}
+			ipa_get_if_index(event_wan.name, &(data_iptype->if_index));
+			data_iptype->iptype = event_wan.ip;
+			IPACMDBG("Received WAN_UPSTREAM_ROUTE_ADD: fid(%d) ip-type(%d)\n", data_iptype->if_index, data_iptype->iptype);
+			evt_data.event = IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT;
+			evt_data.evt_data = data_iptype;
+			break;
+		case WAN_UPSTREAM_ROUTE_DEL:
+			memcpy(&event_wan, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_wan_msg));
+			IPACMDBG("Received WAN_UPSTREAM_ROUTE_DEL name: %s\n",event_wan.name);
+            data_iptype = (ipacm_event_data_iptype *)malloc(sizeof(ipacm_event_data_iptype));
+			if(data_iptype == NULL)
+			{
+				IPACMERR("unable to allocate memory for event_ecm data_iptype\n");
+				return NULL;
+			}
+			ipa_get_if_index(event_wan.name, &(data_iptype->if_index));
+			data_iptype->iptype = event_wan.ip;
+			IPACMDBG("Received WAN_UPSTREAM_ROUTE_DEL: fid(%d) ip-type(%d)\n", data_iptype->if_index, data_iptype->iptype);
+			evt_data.event = IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT;
+			evt_data.evt_data = data_iptype;
+			break;
+        /* End of adding for 8994 Android case */
+
 		default:
 			IPACMDBG("Unhandled message type: %d\n", event_hdr.msg_type);
 			continue;
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
index 2c02e31..c84c532 100644
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.cpp
@@ -391,6 +391,103 @@
 		}
 		break;
 
+#ifdef FEATURE_IPA_ANDROID
+	case IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT:
+		{
+			ipacm_event_data_iptype *data = (ipacm_event_data_iptype *)param;
+			ipa_interface_index = iface_ipa_index_query(data->if_index);
+			if (ipa_interface_index == ipa_if_num)
+			{
+				IPACMDBG("Received IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT (Android) for ip-type (%d)\n", data->iptype);
+				/* The special below condition is to handle default gateway */
+				if ((data->iptype == IPA_IP_v4) && (active_v4 == false))
+				{
+					IPACMDBG("adding routing table(upstream), dev (%s) ip-type(%d)\n", dev_name,data->iptype);
+					handle_route_add_evt(data->iptype);
+				}
+				else if ((data->iptype == IPA_IP_v6) && (active_v6 == false))
+				{
+					IPACMDBG("\n get default v6 route (dst:00.00.00.00) upstream\n");
+				  	handle_route_add_evt(data->iptype);
+				}
+			}
+			else /* double check if current default iface is not itself */
+			{
+				if ((data->iptype == IPA_IP_v4) && (active_v4 == true))
+				{
+					IPACMDBG("Received v4 IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
+					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) && (active_v6 == true))
+				{
+				    IPACMDBG("Received v6 IPA_WAN_UPSTREAM_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;
+
+	case IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT:
+		{
+			ipacm_event_data_iptype *data = (ipacm_event_data_iptype *)param;
+			ipa_interface_index = iface_ipa_index_query(data->if_index);
+			if (ipa_interface_index == ipa_if_num)
+			{
+				IPACMDBG("Received IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT\n");
+				if ((data->iptype == IPA_IP_v4) && (active_v4 == true))
+				{
+					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) && (active_v6 == true))
+				{
+					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;
+#else/* defined(FEATURE_IPA_ANDROID) */
 	case IPA_ROUTE_ADD_EVENT:
 		{
 			ipacm_event_data_addr *data = (ipacm_event_data_addr *)param;
@@ -404,8 +501,8 @@
 				/* The special below condition is to handle default gateway */
 				if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == false))
 				{
-					IPACMDBG("adding routing table\n");
-				  handle_route_add_evt(data->iptype);
+					IPACMDBG("adding routing table, dev (%s) ip-type(%d)\n", dev_name,data->iptype);
+					handle_route_add_evt(data->iptype);
 				}
 				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 == false))
@@ -413,7 +510,7 @@
 					IPACMDBG("\n get default v6 route (dst:00.00.00.00)\n");
 					IPACMDBG(" IPV6 value: %08x:%08x:%08x:%08x \n",
 									 data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]);
-				  	handle_route_add_evt(data->iptype);
+				handle_route_add_evt(data->iptype);
 				}
 			}
 			else /* double check if current default iface is not itself */
@@ -466,7 +563,6 @@
 				if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == true))
 				{
 					IPACMDBG("get del default v4 route (dst:0.0.0.0)\n");
-
 					if(m_is_sta_mode == Q6_WAN)
 					{
 						del_wan_firewall_rule(IPA_IP_v4);
@@ -481,8 +577,8 @@
 				}
 				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("get del default v6 route (dst:00.00.00.00)\n");
 
+				    IPACMDBG("get del default v6 route (dst:00.00.00.00)\n");
 					if(m_is_sta_mode == Q6_WAN)
 					{
 						del_wan_firewall_rule(IPA_IP_v6);
@@ -498,7 +594,7 @@
 			}
 		}
 		break;
-
+#endif /* not defined(FEATURE_IPA_ANDROID)*/
 	case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT:
 		{
 			ipacm_event_data_all *data = (ipacm_event_data_all *)param;