IPACM: Fix the ipv6-only AP+STA use-case

For ipv6-only AP+STA, SoftAP won't posting
v6 default route event to IPACM because of
its new feature called priority backhaul.
Therefore IPACM needs to listen for RTPROT_RA
netlink event instead to find the externel
AP's mac and construct the full wlan header.

Change-Id: I8fb0135f473e31bb87b46f4a437292dc7931f722
Acked-by: Skylar Chang <chiaweic@codeaurora.org>
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index b424d97..421f400 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -305,6 +305,7 @@
 	uint32_t  ipv4_addr_mask;
 	uint32_t  ipv6_addr[4];
 	uint32_t  ipv6_addr_mask[4];
+	uint32_t  ipv6_addr_gw[4];
 } ipacm_event_data_addr;
 
 typedef struct _ipacm_event_data_mac
diff --git a/ipacm/inc/IPACM_Wan.h b/ipacm/inc/IPACM_Wan.h
index 159cc46..dcb8719 100644
--- a/ipacm/inc/IPACM_Wan.h
+++ b/ipacm/inc/IPACM_Wan.h
@@ -155,8 +155,10 @@
 	int num_firewall_v4,num_firewall_v6;
 	uint32_t wan_v4_addr;
 	uint32_t wan_v4_addr_gw;
+	uint32_t wan_v6_addr_gw[4];
 	bool wan_v4_addr_set;
 	bool wan_v4_addr_gw_set;
+	bool wan_v6_addr_gw_set;
 	bool active_v4;
 	bool active_v6;
 	bool header_set_v4;
@@ -261,6 +263,49 @@
 		return IPACM_INVALID_INDEX;
 	}
 
+	inline int get_wan_client_index_ipv6(uint32_t* ipv6_addr)
+	{
+		int cnt, v6_num;
+		int num_wan_client_tmp = num_wan_client;
+
+		IPACMDBG_H("Get ipv6 address 0x%08x.0x%08x.0x%08x.0x%08x\n", ipv6_addr[0], ipv6_addr[1], ipv6_addr[2], ipv6_addr[3]);
+
+		for(cnt = 0; cnt < num_wan_client_tmp; cnt++)
+		{
+			if (get_client_memptr(wan_client, cnt)->ipv6_set)
+			{
+			    for(v6_num=0;v6_num < get_client_memptr(wan_client, cnt)->ipv6_set;v6_num++)
+	            {
+
+					IPACMDBG_H("stored IPv6 0x%08x.0x%08x.0x%08x.0x%08x\n", get_client_memptr(wan_client, cnt)->v6_addr[v6_num][0],
+						get_client_memptr(wan_client, cnt)->v6_addr[v6_num][1],
+						get_client_memptr(wan_client, cnt)->v6_addr[v6_num][2],
+						get_client_memptr(wan_client, cnt)->v6_addr[v6_num][3]);
+
+					if(ipv6_addr[0] == get_client_memptr(wan_client, cnt)->v6_addr[v6_num][0] &&
+					   ipv6_addr[1] == get_client_memptr(wan_client, cnt)->v6_addr[v6_num][1] &&
+					   ipv6_addr[2]== get_client_memptr(wan_client, cnt)->v6_addr[v6_num][2] &&
+					   ipv6_addr[3] == get_client_memptr(wan_client, cnt)->v6_addr[v6_num][3])
+					{
+						IPACMDBG_H("Matched client index: %d\n", cnt);
+						IPACMDBG_H("The MAC is %02x:%02x:%02x:%02x:%02x:%02x\n",
+								get_client_memptr(wan_client, cnt)->mac[0],
+								get_client_memptr(wan_client, cnt)->mac[1],
+								get_client_memptr(wan_client, cnt)->mac[2],
+								get_client_memptr(wan_client, cnt)->mac[3],
+								get_client_memptr(wan_client, cnt)->mac[4],
+								get_client_memptr(wan_client, cnt)->mac[5]);
+						IPACMDBG_H("header set ipv4(%d) ipv6(%d)\n",
+								get_client_memptr(wan_client, cnt)->ipv4_header_set,
+								get_client_memptr(wan_client, cnt)->ipv6_header_set);
+						return cnt;
+					}
+				}
+			}
+		}
+		return IPACM_INVALID_INDEX;
+	}
+
 	inline int delete_wan_rtrules(int clt_indx, ipa_ip_type iptype)
 	{
 		uint32_t tx_index;
diff --git a/ipacm/src/IPACM_Netlink.cpp b/ipacm/src/IPACM_Netlink.cpp
index 3dfc514..a343e24 100644
--- a/ipacm/src/IPACM_Netlink.cpp
+++ b/ipacm/src/IPACM_Netlink.cpp
@@ -879,7 +879,6 @@
 
 			IPACMDBG("In case RTM_NEWROUTE\n");
 			IPACMDBG("rtm_type: %d\n", msg_ptr->nl_route_info.metainfo.rtm_type);
-			IPACMDBG("rtm_type: %d\n", msg_ptr->nl_route_info.metainfo.rtm_type);
 			IPACMDBG("protocol: %d\n", msg_ptr->nl_route_info.metainfo.rtm_protocol);
 			IPACMDBG("rtm_scope: %d\n", msg_ptr->nl_route_info.metainfo.rtm_scope);
 			IPACMDBG("rtm_table: %d\n", msg_ptr->nl_route_info.metainfo.rtm_table);
@@ -888,7 +887,8 @@
 
 			/* take care of route add default route & uniroute */
 			if((msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) &&
-				 (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_BOOT) &&
+				 ((msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_BOOT) ||
+				  (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_RA)) &&
 				 (msg_ptr->nl_route_info.metainfo.rtm_scope == RT_SCOPE_UNIVERSE) &&
 				 (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN))
 			{
@@ -967,13 +967,20 @@
 						data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]);
 						data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]);
 						data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]);
-						IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr);
 
+						IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr);
 						data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]);
 						data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]);
 						data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]);
 						data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]);
 
+						IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_gw, msg_ptr->nl_route_info.attr_info.gateway_addr);
+						data_addr->ipv6_addr_gw[0] = ntohl(data_addr->ipv6_addr_gw[0]);
+						data_addr->ipv6_addr_gw[1] = ntohl(data_addr->ipv6_addr_gw[1]);
+						data_addr->ipv6_addr_gw[2] = ntohl(data_addr->ipv6_addr_gw[2]);
+						data_addr->ipv6_addr_gw[3] = ntohl(data_addr->ipv6_addr_gw[3]);
+						IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_route_info.attr_info.gateway_addr);
+
 						evt_data.event = IPA_ROUTE_ADD_EVENT;
 						data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index;
 						data_addr->iptype = IPA_IP_v6;
@@ -1146,7 +1153,8 @@
 			}
 			/* take care of route delete of default route & uniroute */
 			if((msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) &&
-				 (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_BOOT) &&
+				 ((msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_BOOT) ||
+				  (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_RA)) &&
 				 (msg_ptr->nl_route_info.metainfo.rtm_scope == 0) &&
 				 (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN))
 			{
@@ -1217,19 +1225,24 @@
 						{
 							IPACMDBG("ip -6 route del default dev %s\n", dev_name);
 						}
-						 IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr);
-
+						IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr);
 						data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]);
 						data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]);
 						data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]);
 						data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]);
 
 						IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr);
-
 						data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]);
 						data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]);
 						data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]);
 						data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]);
+
+						IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_gw, msg_ptr->nl_route_info.attr_info.gateway_addr);
+						data_addr->ipv6_addr_gw[0] = ntohl(data_addr->ipv6_addr_gw[0]);
+						data_addr->ipv6_addr_gw[1] = ntohl(data_addr->ipv6_addr_gw[1]);
+						data_addr->ipv6_addr_gw[2] = ntohl(data_addr->ipv6_addr_gw[2]);
+						data_addr->ipv6_addr_gw[3] = ntohl(data_addr->ipv6_addr_gw[3]);
+						IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_route_info.attr_info.gateway_addr);
 						data_addr->iptype = IPA_IP_v6;
 					}
 					else
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
index 6381826..f9c1fb6 100644
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.cpp
@@ -96,6 +96,7 @@
 
 	wan_v4_addr_set = false;
 	wan_v4_addr_gw_set = false;
+	wan_v6_addr_gw_set = false;
 	active_v4 = false;
 	active_v6 = false;
 	header_set_v4 = false;
@@ -107,6 +108,7 @@
 	num_ipv6_dest_flt_rule = 0;
 	memset(ipv6_dest_flt_rule_hdl, 0, MAX_DEFAULT_v6_ROUTE_RULES*sizeof(uint32_t));
 	memset(ipv6_prefix, 0, sizeof(ipv6_prefix));
+	memset(wan_v6_addr_gw, 0, sizeof(wan_v6_addr_gw));
 	ext_prop = NULL;
 
 	num_wan_client = 0;
@@ -832,8 +834,17 @@
 						(active_v6 == false) &&	(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX))
 				{
 					IPACMDBG_H("\n get default v6 route (dst:00.00.00.00)\n");
-					IPACMDBG_H(" IPV6 value: %08x:%08x:%08x:%08x \n",
+					IPACMDBG_H(" IPV6 dst: %08x:%08x:%08x:%08x \n",
 							data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]);
+					IPACMDBG_H(" IPV6 gateway: %08x:%08x:%08x:%08x \n",
+							data->ipv6_addr_gw[0], data->ipv6_addr_gw[1], data->ipv6_addr_gw[2], data->ipv6_addr_gw[3]);
+					wan_v6_addr_gw[0] = data->ipv6_addr_gw[0];
+					wan_v6_addr_gw[1] = data->ipv6_addr_gw[1];
+					wan_v6_addr_gw[2] = data->ipv6_addr_gw[2];
+					wan_v6_addr_gw[3] = data->ipv6_addr_gw[3];
+					wan_v6_addr_gw_set = true;
+					/* Check & construct STA header */
+					handle_sta_header_add_evt();
 					handle_route_add_evt(data->iptype);
 				}
 			}
@@ -1557,6 +1568,51 @@
 		}
 	}
 
+	/* checking if the ipv4 same as default route */
+	if(wan_v6_addr_gw_set)
+	{
+		index = get_wan_client_index_ipv6(wan_v6_addr_gw);
+		if (index != IPACM_INVALID_INDEX)
+		{
+			IPACMDBG_H("Matched client index: %d\n", index);
+			IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+					 get_client_memptr(wan_client, index)->mac[0],
+					 get_client_memptr(wan_client, index)->mac[1],
+					 get_client_memptr(wan_client, index)->mac[2],
+					 get_client_memptr(wan_client, index)->mac[3],
+					 get_client_memptr(wan_client, index)->mac[4],
+					 get_client_memptr(wan_client, index)->mac[5]);
+			if(get_client_memptr(wan_client, index)->ipv6_header_set)
+			{
+				hdr_hdl_sta_v6 = get_client_memptr(wan_client, index)->hdr_hdl_v6;
+				header_set_v6 = true;
+				IPACMDBG_H("add full ipv6 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v6);
+			}
+			else
+			{
+				IPACMERR(" wan-client got ipv6 however didn't construct complete ipv4 header \n");
+				return IPACM_FAILURE;
+			}
+
+			if(get_client_memptr(wan_client, index)->ipv4_header_set)
+			{
+				hdr_hdl_sta_v4 = get_client_memptr(wan_client, index)->hdr_hdl_v4;
+				header_set_v4 = true;
+				IPACMDBG_H("add full ipv4 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v4);
+			}
+			else
+			{
+				IPACMERR(" wan-client got ipv4 however didn't construct complete ipv4 header \n");
+				return IPACM_FAILURE;
+			}
+		}
+		else
+		{
+			IPACMDBG_H(" currently can't find matched wan-client's MAC-addr, waiting for header construction\n");
+			return IPACM_SUCCESS;
+		}
+	}
+
 	/* see if default routes are setup before constructing full header */
 	if(header_partial_default_wan_v4 == true)
 	{