Home | History | Annotate | Download | only in src
      1 /*
      2 Copyright (c) 2013, The Linux Foundation. All rights reserved.
      3 
      4 Redistribution and use in source and binary forms, with or without
      5 modification, are permitted provided that the following conditions are
      6 met:
      7 		* Redistributions of source code must retain the above copyright
      8 			notice, this list of conditions and the following disclaimer.
      9 		* Redistributions in binary form must reproduce the above
     10 			copyright notice, this list of conditions and the following
     11 			disclaimer in the documentation and/or other materials provided
     12 			with the distribution.
     13 		* Neither the name of The Linux Foundation nor the names of its
     14 			contributors may be used to endorse or promote products derived
     15 			from this software without specific prior written permission.
     16 
     17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 */
     29 /*!
     30 		@file
     31 		IPACM_Wan.cpp
     32 
     33 		@brief
     34 		This file implements the WAN iface functionality.
     35 
     36 		@Author
     37 		Skylar Chang
     38 
     39 */
     40 #include <string.h>
     41 #include <fcntl.h>
     42 #include <sys/ioctl.h>
     43 #include <IPACM_Wan.h>
     44 #include <IPACM_Xml.h>
     45 #include <IPACM_Log.h>
     46 #include "IPACM_EvtDispatcher.h"
     47 #include <IPACM_IfaceManager.h>
     48 #include "linux/rmnet_ipa_fd_ioctl.h"
     49 #include "IPACM_Config.h"
     50 #include "IPACM_Defs.h"
     51 #include <IPACM_ConntrackListener.h>
     52 #include "linux/ipa_qmi_service_v01.h"
     53 #ifdef FEATURE_IPACM_HAL
     54 #include "IPACM_OffloadManager.h"
     55 #endif
     56 
     57 bool IPACM_Wan::wan_up = false;
     58 bool IPACM_Wan::wan_up_v6 = false;
     59 uint8_t IPACM_Wan::xlat_mux_id = 0;
     60 
     61 uint32_t IPACM_Wan::curr_wan_ip = 0;
     62 int IPACM_Wan::num_v4_flt_rule = 0;
     63 int IPACM_Wan::num_v6_flt_rule = 0;
     64 
     65 struct ipa_flt_rule_add IPACM_Wan::flt_rule_v4[IPA_MAX_FLT_RULE];
     66 struct ipa_flt_rule_add IPACM_Wan::flt_rule_v6[IPA_MAX_FLT_RULE];
     67 
     68 char IPACM_Wan::wan_up_dev_name[IF_NAME_LEN];
     69 
     70 bool IPACM_Wan::backhaul_is_sta_mode = false;
     71 bool IPACM_Wan::is_ext_prop_set = false;
     72 
     73 int IPACM_Wan::num_ipv4_modem_pdn = 0;
     74 int IPACM_Wan::num_ipv6_modem_pdn = 0;
     75 
     76 bool IPACM_Wan::embms_is_on = false;
     77 bool IPACM_Wan::backhaul_is_wan_bridge = false;
     78 
     79 uint32_t IPACM_Wan::backhaul_ipv6_prefix[2];
     80 
     81 #ifdef FEATURE_IPA_ANDROID
     82 uint32_t	IPACM_Wan::ipa_if_num_tether_v4_total = 0;
     83 uint32_t	IPACM_Wan::ipa_if_num_tether_v6_total = 0;
     84 
     85 int	IPACM_Wan::ipa_if_num_tether_v4[IPA_MAX_IFACE_ENTRIES];
     86 int	IPACM_Wan::ipa_if_num_tether_v6[IPA_MAX_IFACE_ENTRIES];
     87 #endif
     88 
     89 IPACM_Wan::IPACM_Wan(int iface_index,
     90 	ipacm_wan_iface_type is_sta_mode,
     91 	uint8_t *mac_addr) : IPACM_Iface(iface_index)
     92 {
     93 	num_firewall_v4 = 0;
     94 	num_firewall_v6 = 0;
     95 	wan_route_rule_v4_hdl = NULL;
     96 	wan_route_rule_v6_hdl = NULL;
     97 	wan_route_rule_v6_hdl_a5 = NULL;
     98 	wan_client = NULL;
     99 	mac_addr = NULL;
    100 
    101 	if(iface_query != NULL)
    102 	{
    103 		wan_route_rule_v4_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t));
    104 		wan_route_rule_v6_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t));
    105 		wan_route_rule_v6_hdl_a5 = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t));
    106 		IPACMDBG_H("IPACM->IPACM_Wan(%d) constructor: Tx:%d\n", ipa_if_num, iface_query->num_tx_props);
    107 	}
    108 	m_is_sta_mode = is_sta_mode;
    109 
    110 	wan_v4_addr_set = false;
    111 	wan_v4_addr_gw_set = false;
    112 	wan_v6_addr_gw_set = false;
    113 	active_v4 = false;
    114 	active_v6 = false;
    115 	header_set_v4 = false;
    116 	header_set_v6 = false;
    117 	header_partial_default_wan_v4 = false;
    118 	header_partial_default_wan_v6 = false;
    119 	hdr_hdl_sta_v4 = 0;
    120 	hdr_hdl_sta_v6 = 0;
    121 	num_ipv6_dest_flt_rule = 0;
    122 	memset(ipv6_dest_flt_rule_hdl, 0, MAX_DEFAULT_v6_ROUTE_RULES*sizeof(uint32_t));
    123 	memset(ipv6_prefix, 0, sizeof(ipv6_prefix));
    124 	memset(wan_v6_addr_gw, 0, sizeof(wan_v6_addr_gw));
    125 	ext_prop = NULL;
    126 	is_ipv6_frag_firewall_flt_rule_installed = false;
    127 	ipv6_frag_firewall_flt_rule_hdl = 0;
    128 
    129 	num_wan_client = 0;
    130 	header_name_count = 0;
    131 	memset(invalid_mac, 0, sizeof(invalid_mac));
    132 
    133 	is_xlat = false;
    134 	hdr_hdl_dummy_v6 = 0;
    135 	hdr_proc_hdl_dummy_v6 = 0;
    136 	is_default_gateway = false;
    137 	m_fd_ipa = 0;
    138 	wan_client_len = 0;
    139 
    140 	if(iface_query != NULL)
    141 	{
    142 		wan_client_len = (sizeof(ipa_wan_client)) + (iface_query->num_tx_props * sizeof(wan_client_rt_hdl));
    143 		wan_client = (ipa_wan_client *)calloc(IPA_MAX_NUM_WAN_CLIENTS, wan_client_len);
    144 		if (wan_client == NULL)
    145 		{
    146 			IPACMERR("unable to allocate memory\n");
    147 			return;
    148 		}
    149 		IPACMDBG_H("index:%d constructor: Tx properties:%d\n", iface_index, iface_query->num_tx_props);
    150 	}
    151 
    152 
    153 	if(m_is_sta_mode == Q6_WAN)
    154 	{
    155 		IPACMDBG_H("The new WAN interface is modem.\n");
    156 		is_default_gateway = false;
    157 		query_ext_prop();
    158 	}
    159 	else
    160 	{
    161 		IPACMDBG_H("The new WAN interface is WLAN STA.\n");
    162 	}
    163 
    164 	m_fd_ipa = open(IPA_DEVICE_NAME, O_RDWR);
    165 	if(0 == m_fd_ipa)
    166 	{
    167 		IPACMERR("Failed to open %s\n",IPA_DEVICE_NAME);
    168 	}
    169 
    170 	if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == EMBMS_IF)
    171 	{
    172 		IPACMDBG(" IPACM->IPACM_Wan_eMBMS(%d)\n", ipa_if_num);
    173 		embms_is_on = true;
    174 		install_wan_filtering_rule(false);
    175 		/* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */
    176 		if(tx_prop != NULL)
    177 		{
    178 			IPACMDBG_H("dev %s add producer dependency\n", dev_name);
    179 			IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
    180         	IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false);
    181 		}
    182 	}
    183 	else
    184 	{
    185 		IPACMDBG(" IPACM->IPACM_Wan(%d)\n", ipa_if_num);
    186 	}
    187 	return;
    188 }
    189 
    190 IPACM_Wan::~IPACM_Wan()
    191 {
    192 	IPACM_EvtDispatcher::deregistr(this);
    193 	IPACM_IfaceManager::deregistr(this);
    194 	return;
    195 }
    196 
    197 /* handle new_address event */
    198 int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data)
    199 {
    200 	struct ipa_ioc_add_rt_rule *rt_rule = NULL;
    201 	struct ipa_rt_rule_add *rt_rule_entry;
    202 	struct ipa_ioc_add_flt_rule *flt_rule;
    203 	struct ipa_flt_rule_add flt_rule_entry;
    204 	struct ipa_ioc_get_hdr hdr;
    205 
    206 	const int NUM_RULES = 1;
    207 	uint32_t num_ipv6_addr;
    208 	int res = IPACM_SUCCESS,len;
    209 #ifdef FEATURE_IPACM_HAL
    210 	IPACM_OffloadManager* OffloadMng;
    211 #endif
    212 
    213 	memset(&hdr, 0, sizeof(hdr));
    214 	if(tx_prop == NULL || rx_prop == NULL)
    215 	{
    216 		IPACMDBG_H("Either tx or rx property is NULL, return.\n");
    217 		return IPACM_SUCCESS;
    218 	}
    219 
    220 	/* Update the IP Type. */
    221 	config_ip_type(data->iptype);
    222 
    223 	if (data->iptype == IPA_IP_v6)
    224 	{
    225 		for(num_ipv6_addr=0;num_ipv6_addr<num_dft_rt_v6;num_ipv6_addr++)
    226 		{
    227 			if((ipv6_addr[num_ipv6_addr][0] == data->ipv6_addr[0]) &&
    228 			   (ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) &&
    229 			   (ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) &&
    230 			   (ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3]))
    231 			{
    232 				IPACMDBG_H("find matched ipv6 address, index:%d \n", num_ipv6_addr);
    233 				return IPACM_SUCCESS;
    234 				break;
    235 			}
    236 		}
    237 		rt_rule = (struct ipa_ioc_add_rt_rule *)
    238 			calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
    239 				NUM_RULES * sizeof(struct ipa_rt_rule_add));
    240 
    241 		if (!rt_rule)
    242 		{
    243 			IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n");
    244 			return IPACM_FAILURE;
    245 		}
    246 
    247 		rt_rule->commit = 1;
    248 		rt_rule->num_rules = NUM_RULES;
    249 		rt_rule->ip = data->iptype;
    250 		strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name));
    251 
    252 		rt_rule_entry = &rt_rule->rules[0];
    253 		if(m_is_sta_mode == Q6_WAN)
    254 		{
    255 			strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
    256 			hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
    257 			if(m_header.GetHeaderHandle(&hdr) == false)
    258 			{
    259 				IPACMERR("Failed to get QMAP header.\n");
    260 				return IPACM_FAILURE;
    261 			}
    262 			rt_rule_entry->rule.hdr_hdl = hdr.hdl;
    263 		}
    264 		rt_rule_entry->at_rear = false;
    265 		if(m_is_sta_mode == Q6_WAN)
    266 		{
    267 			rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS;
    268 		}
    269 		else
    270 		{
    271 			rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS;
    272 		}
    273 		rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
    274 		rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0];
    275 		rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1];
    276 		rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2];
    277 		rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = data->ipv6_addr[3];
    278 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
    279 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
    280 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
    281 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
    282 		ipv6_addr[num_dft_rt_v6][0] = data->ipv6_addr[0];
    283 		ipv6_addr[num_dft_rt_v6][1] = data->ipv6_addr[1];
    284 		ipv6_addr[num_dft_rt_v6][2] = data->ipv6_addr[2];
    285 		ipv6_addr[num_dft_rt_v6][3] = data->ipv6_addr[3];
    286 #ifdef FEATURE_IPA_V3
    287 		rt_rule_entry->rule.hashable = false;
    288 #endif
    289 		if (false == m_routing.AddRoutingRule(rt_rule))
    290 		{
    291 			IPACMERR("Routing rule addition failed!\n");
    292 			res = IPACM_FAILURE;
    293 			goto fail;
    294 		}
    295 		else if (rt_rule_entry->status)
    296 		{
    297 			IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
    298 			res = rt_rule_entry->status;
    299 			goto fail;
    300 		}
    301 		dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl;
    302 
    303 		/* setup same rule for v6_wan table*/
    304 		strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name));
    305 		if (false == m_routing.AddRoutingRule(rt_rule))
    306 		{
    307 			IPACMERR("Routing rule addition failed!\n");
    308 			res = IPACM_FAILURE;
    309 			goto fail;
    310 		}
    311 		else if (rt_rule_entry->status)
    312 		{
    313 			IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
    314 			res = rt_rule_entry->status;
    315 			goto fail;
    316 		}
    317 		dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl;
    318 
    319 		IPACMDBG_H("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, num_dft_rt_v6: %d \n",
    320 				dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6],
    321 				dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1],num_dft_rt_v6);
    322 
    323 		/* add default filtering rules when wan-iface get global v6-prefix */
    324 		if (num_dft_rt_v6 == 1)
    325 		{
    326 			if(m_is_sta_mode == Q6_WAN)
    327 			{
    328 				modem_ipv6_pdn_index = num_ipv6_modem_pdn;
    329 				num_ipv6_modem_pdn++;
    330 				IPACMDBG_H("Now the number of modem ipv6 pdn is %d.\n", num_ipv6_modem_pdn);
    331 				init_fl_rule_ex(data->iptype);
    332 			}
    333 			else
    334 			{
    335 				init_fl_rule(data->iptype);
    336 			}
    337 		}
    338 
    339 		/* add WAN DL interface IP specific flt rule for IPv6 when backhaul is not Q6 */
    340 		if(m_is_sta_mode != Q6_WAN)
    341 		{
    342 			if(rx_prop != NULL && is_global_ipv6_addr(data->ipv6_addr)
    343 				&& num_ipv6_dest_flt_rule < MAX_DEFAULT_v6_ROUTE_RULES)
    344 			{
    345 				len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add);
    346 
    347 				flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
    348 				if (!flt_rule)
    349 				{
    350 					IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
    351 					return IPACM_FAILURE;
    352 				}
    353 
    354 				flt_rule->commit = 1;
    355 				flt_rule->ep = rx_prop->rx[0].src_pipe;
    356 				flt_rule->global = false;
    357 				flt_rule->ip = IPA_IP_v6;
    358 				flt_rule->num_rules = 1;
    359 
    360 				memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
    361 
    362 				flt_rule_entry.rule.retain_hdr = 1;
    363 				flt_rule_entry.rule.to_uc = 0;
    364 				flt_rule_entry.rule.eq_attrib_type = 0;
    365 				flt_rule_entry.at_rear = true;
    366 				flt_rule_entry.flt_rule_hdl = -1;
    367 				flt_rule_entry.status = -1;
    368 				flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
    369 #ifdef FEATURE_IPA_V3
    370 				flt_rule_entry.rule.hashable = true;
    371 #endif
    372 				memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
    373 
    374 				flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
    375 				memcpy(flt_rule_entry.rule.attrib.u.v6.dst_addr, data->ipv6_addr, sizeof(flt_rule_entry.rule.attrib.u.v6.dst_addr));
    376 				flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
    377 				flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
    378 				flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
    379 				flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
    380 				memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
    381 
    382 				if (m_filtering.AddFilteringRule(flt_rule) == false)
    383 				{
    384 					IPACMERR("Error Adding Filtering rule, aborting...\n");
    385 					free(flt_rule);
    386 					res = IPACM_FAILURE;
    387 					goto fail;
    388 				}
    389 				else
    390 				{
    391 					IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
    392 					ipv6_dest_flt_rule_hdl[num_ipv6_dest_flt_rule] = flt_rule->rules[0].flt_rule_hdl;
    393 					IPACMDBG_H("IPv6 dest filter rule %d HDL:0x%x\n", num_ipv6_dest_flt_rule, ipv6_dest_flt_rule_hdl[num_ipv6_dest_flt_rule]);
    394 					num_ipv6_dest_flt_rule++;
    395 					free(flt_rule);
    396 				}
    397 			}
    398 		}
    399 		/* store ipv6 prefix if the ipv6 address is not link local */
    400 		if(is_global_ipv6_addr(data->ipv6_addr))
    401 		{
    402 			memcpy(ipv6_prefix, data->ipv6_addr, sizeof(ipv6_prefix));
    403 		}
    404 	    num_dft_rt_v6++;
    405     }
    406 	else
    407 	{
    408 		if(wan_v4_addr_set)
    409 		{
    410 			/* check iface ipv4 same or not */
    411 			if(data->ipv4_addr == wan_v4_addr)
    412 			{
    413 				IPACMDBG_H("Already setup device (%s) ipv4 and it didn't change(0x%x)\n", dev_name, data->ipv4_addr);
    414 				return IPACM_SUCCESS;
    415 			}
    416 			else
    417 			{
    418 				IPACMDBG_H(" device (%s) ipv4 addr is changed\n", dev_name);
    419 				/* Delete default v4 RT rule */
    420 				IPACMDBG_H("Delete default v4 routing rules\n");
    421 				if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
    422 				{
    423 					IPACMERR("Routing old RT rule deletion failed!\n");
    424 					res = IPACM_FAILURE;
    425 					goto fail;
    426 				}
    427 			}
    428 		}
    429 
    430 		rt_rule = (struct ipa_ioc_add_rt_rule *)
    431 			 calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
    432 							NUM_RULES * sizeof(struct ipa_rt_rule_add));
    433 
    434 		if (!rt_rule)
    435 		{
    436 			IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n");
    437 			return IPACM_FAILURE;
    438 		}
    439 
    440 		rt_rule->commit = 1;
    441 		rt_rule->num_rules = NUM_RULES;
    442 		rt_rule->ip = data->iptype;
    443 		rt_rule_entry = &rt_rule->rules[0];
    444 		if(m_is_sta_mode == Q6_WAN)
    445 		{
    446 			strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
    447 			hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
    448 			if(m_header.GetHeaderHandle(&hdr) == false)
    449 			{
    450 				IPACMERR("Failed to get QMAP header.\n");
    451 				return IPACM_FAILURE;
    452 			}
    453 			rt_rule_entry->rule.hdr_hdl = hdr.hdl;
    454 			rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS;
    455 		}
    456 		else
    457 		{
    458 			rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS;
    459 		}
    460 		rt_rule_entry->at_rear = false;
    461 		rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
    462 		/* still need setup v4 default routing rule to A5*/
    463 		strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name));
    464 		rt_rule_entry->rule.attrib.u.v4.dst_addr      = data->ipv4_addr;
    465 		rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
    466 #ifdef FEATURE_IPA_V3
    467 		rt_rule_entry->rule.hashable = false;
    468 #endif
    469 		if (false == m_routing.AddRoutingRule(rt_rule))
    470 		{
    471 			IPACMERR("Routing rule addition failed!\n");
    472 			res = IPACM_FAILURE;
    473 			goto fail;
    474 		}
    475 		else if (rt_rule_entry->status)
    476 		{
    477 			IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
    478 			res = rt_rule_entry->status;
    479 			goto fail;
    480 		}
    481 		dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
    482 		IPACMDBG_H("ipv4 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[0]);
    483 			/* initial multicast/broadcast/fragment filter rule */
    484 
    485 		/* only do one time */
    486 		if(!wan_v4_addr_set)
    487 		{
    488 			/* initial multicast/broadcast/fragment filter rule */
    489 			if(m_is_sta_mode == Q6_WAN)
    490 			{
    491 				modem_ipv4_pdn_index = num_ipv4_modem_pdn;
    492 				num_ipv4_modem_pdn++;
    493 				IPACMDBG_H("Now the number of modem ipv4 pdn is %d.\n", num_ipv4_modem_pdn);
    494 				init_fl_rule_ex(data->iptype);
    495 			}
    496 			else
    497 			{
    498 				init_fl_rule(data->iptype);
    499 			}
    500 		}
    501 
    502 		wan_v4_addr = data->ipv4_addr;
    503 		wan_v4_addr_set = true;
    504 
    505 		if (m_is_sta_mode == Q6_WAN)
    506 			curr_wan_ip = data->ipv4_addr;
    507 
    508 		IPACMDBG_H("Receved wan ipv4-addr:0x%x\n",wan_v4_addr);
    509 	}
    510 
    511 #ifdef FEATURE_IPACM_HAL
    512 	/* check if having pending add_downstream cache*/
    513 	OffloadMng = IPACM_OffloadManager::GetInstance();
    514 	if (OffloadMng == NULL) {
    515 		IPACMERR("failed to get IPACM_OffloadManager instance !\n");
    516 	} else {
    517 		IPACMDBG_H(" check iface %s if having add_downstream cache events\n", dev_name);
    518 		OffloadMng->search_framwork_cache(dev_name);
    519 	}
    520 #endif
    521 	IPACMDBG_H("number of default route rules %d\n", num_dft_rt_v6);
    522 
    523 fail:
    524 	free(rt_rule);
    525 
    526 	return res;
    527 }
    528 
    529 void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param)
    530 {
    531 	int ipa_interface_index;
    532 
    533 	switch (event)
    534 	{
    535 	case IPA_WLAN_LINK_DOWN_EVENT:
    536 		{
    537 			if(m_is_sta_mode == WLAN_WAN)
    538 			{
    539 				ipacm_event_data_fid *data = (ipacm_event_data_fid *)param;
    540 				ipa_interface_index = iface_ipa_index_query(data->if_index);
    541 				if (ipa_interface_index == ipa_if_num)
    542 				{
    543 					IPACMDBG_H("Received IPA_WLAN_LINK_DOWN_EVENT\n");
    544 					handle_down_evt();
    545 					/* reset the STA-iface category to unknown */
    546 					IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat = UNKNOWN_IF;
    547 					IPACMDBG_H("IPA_WAN_STA (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num);
    548 					IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
    549 					delete this;
    550 					return;
    551 				}
    552 			}
    553 		}
    554 		break;
    555 
    556 	case IPA_WAN_XLAT_CONNECT_EVENT:
    557 		{
    558 			IPACMDBG_H("Recieved IPA_WAN_XLAT_CONNECT_EVENT\n");
    559 			ipacm_event_data_fid *data = (ipacm_event_data_fid *)param;
    560 			ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data->if_index);
    561 			if ((ipa_interface_index == ipa_if_num) && (m_is_sta_mode == Q6_WAN))
    562 			{
    563 				is_xlat = true;
    564 				IPACMDBG_H("WAN-LTE (%s) link up, iface: %d is_xlat: %d\n",
    565 						IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,data->if_index, is_xlat);
    566 			}
    567 			break;
    568 		}
    569 	case IPA_CFG_CHANGE_EVENT:
    570 		{
    571 			if ( (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ipa_if_cate) &&
    572 					(m_is_sta_mode ==ECM_WAN))
    573 			{
    574 				IPACMDBG_H("Received IPA_CFG_CHANGE_EVENT and category did not change(wan_mode:%d)\n", m_is_sta_mode);
    575 				IPACMDBG_H("Now the cradle wan mode is %d.\n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode);
    576 				if(is_default_gateway == true)
    577 				{
    578 					if(backhaul_is_wan_bridge == false && IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == BRIDGE)
    579 					{
    580 						IPACMDBG_H("Cradle wan mode switch to bridge mode.\n");
    581 						backhaul_is_wan_bridge = true;
    582 					}
    583 					else if(backhaul_is_wan_bridge == true && IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
    584 					{
    585 						IPACMDBG_H("Cradle wan mode switch to router mode.\n");
    586 						backhaul_is_wan_bridge = false;
    587 					}
    588 					else
    589 					{
    590 						IPACMDBG_H("No cradle mode switch, return.\n");
    591 						return;
    592 					}
    593 					/* post wan mode change event to LAN/WLAN */
    594 					if(IPACM_Wan::wan_up == true)
    595 					{
    596 						IPACMDBG_H("This interface is default GW.\n");
    597 						ipacm_cmd_q_data evt_data;
    598 						memset(&evt_data, 0, sizeof(evt_data));
    599 
    600 						ipacm_event_cradle_wan_mode *data_wan_mode = NULL;
    601 						data_wan_mode = (ipacm_event_cradle_wan_mode *)malloc(sizeof(ipacm_event_cradle_wan_mode));
    602 						if(data_wan_mode == NULL)
    603 						{
    604 							IPACMERR("unable to allocate memory.\n");
    605 							return;
    606 						}
    607 						data_wan_mode->cradle_wan_mode = IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode;
    608 						evt_data.event = IPA_CRADLE_WAN_MODE_SWITCH;
    609 						evt_data.evt_data = data_wan_mode;
    610 						IPACMDBG_H("Posting IPA_CRADLE_WAN_MODE_SWITCH event.\n");
    611 						IPACM_EvtDispatcher::PostEvt(&evt_data);
    612 					}
    613 					/* update the firewall flt rule actions */
    614 					if(active_v4)
    615 					{
    616 						del_dft_firewall_rules(IPA_IP_v4);
    617 						config_dft_firewall_rules(IPA_IP_v4);
    618 					}
    619 					if(active_v6)
    620 					{
    621 						del_dft_firewall_rules(IPA_IP_v6);
    622 						config_dft_firewall_rules(IPA_IP_v6);
    623 					}
    624 				}
    625 				else
    626 				{
    627 					IPACMDBG_H("This interface is not default GW, ignore.\n");
    628 				}
    629 			}
    630 			else if ( (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat != ipa_if_cate) &&
    631 					(m_is_sta_mode ==ECM_WAN))
    632 			{
    633 				IPACMDBG_H("Received IPA_CFG_CHANGE_EVENT and category changed(wan_mode:%d)\n", m_is_sta_mode);
    634 				/* posting link-up event for cradle use-case */
    635 				ipacm_cmd_q_data evt_data;
    636 				memset(&evt_data, 0, sizeof(evt_data));
    637 
    638 				ipacm_event_data_fid *data_fid = NULL;
    639 				data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid));
    640 				if(data_fid == NULL)
    641 				{
    642 					IPACMERR("unable to allocate memory for IPA_USB_LINK_UP_EVENT data_fid\n");
    643 					return;
    644 				}
    645 				if(IPACM_Iface::ipa_get_if_index(dev_name, &(data_fid->if_index)))
    646 				{
    647 					IPACMERR("Error while getting interface index for %s device", dev_name);
    648 				}
    649 				evt_data.event = IPA_USB_LINK_UP_EVENT;
    650 				evt_data.evt_data = data_fid;
    651 				IPACMDBG_H("Posting event:%d\n", evt_data.event);
    652 				IPACM_EvtDispatcher::PostEvt(&evt_data);
    653 
    654 				/* delete previous instance */
    655 				handle_down_evt();
    656 				IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
    657 				delete this;
    658 				return;
    659 			}
    660 		}
    661 		break;
    662 
    663 	case IPA_LINK_DOWN_EVENT:
    664 		{
    665 			ipacm_event_data_fid *data = (ipacm_event_data_fid *)param;
    666 			ipa_interface_index = iface_ipa_index_query(data->if_index);
    667 			if (ipa_interface_index == ipa_if_num)
    668 			{
    669 				if(m_is_sta_mode == Q6_WAN)
    670 				{
    671 						IPACMDBG_H("Received IPA_LINK_DOWN_EVENT\n");
    672 						handle_down_evt_ex();
    673 						IPACMDBG_H("IPA_WAN_Q6 (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num);
    674 						IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
    675 						delete this;
    676 						return;
    677 				}
    678 				else if (m_is_sta_mode == ECM_WAN)
    679 				{
    680 					IPACMDBG_H("Received IPA_LINK_DOWN_EVENT(wan_mode:%d)\n", m_is_sta_mode);
    681 					/* delete previous instance */
    682 					handle_down_evt();
    683 					IPACMDBG_H("IPA_WAN_CRADLE (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num);
    684 					IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
    685 					delete this;
    686 					return;
    687 				}
    688 			}
    689 		}
    690 		break;
    691 
    692 	case IPA_ADDR_ADD_EVENT:
    693 		{
    694 			ipacm_event_data_addr *data = (ipacm_event_data_addr *)param;
    695 			ipa_interface_index = iface_ipa_index_query(data->if_index);
    696 
    697 			if ( (data->iptype == IPA_IP_v4 && data->ipv4_addr == 0) ||
    698 					 (data->iptype == IPA_IP_v6 &&
    699 						data->ipv6_addr[0] == 0 && data->ipv6_addr[1] == 0 &&
    700 					  data->ipv6_addr[2] == 0 && data->ipv6_addr[3] == 0) )
    701 			{
    702 				IPACMDBG_H("Invalid address, ignore IPA_ADDR_ADD_EVENT event\n");
    703 				return;
    704 			}
    705 
    706 			if (ipa_interface_index == ipa_if_num)
    707 			{
    708 				IPACMDBG_H("Get IPA_ADDR_ADD_EVENT: IF ip type %d, incoming ip type %d\n", ip_type, data->iptype);
    709 				/* check v4 not setup before, v6 can have 2 iface ip */
    710 				if( (data->iptype == IPA_IP_v4)
    711 				    || ((data->iptype==IPA_IP_v6) && (num_dft_rt_v6!=MAX_DEFAULT_v6_ROUTE_RULES)))
    712 				{
    713 					IPACMDBG_H("Got IPA_ADDR_ADD_EVENT ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6);
    714 					handle_addr_evt(data);
    715 					/* checking if SW-RT_enable */
    716 					if (IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true &&
    717 							m_is_sta_mode != Q6_WAN)
    718 					{
    719 						/* handle software routing enable event*/
    720 						IPACMDBG_H("IPA_SW_ROUTING_ENABLE for iface: %s \n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name);
    721 						handle_software_routing_enable();
    722 					}
    723 
    724 				}
    725 			}
    726 		}
    727 		break;
    728 
    729 
    730 	case IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT:
    731 		{
    732 			ipacm_event_data_iptype *data = (ipacm_event_data_iptype *)param;
    733 			ipa_interface_index = iface_ipa_index_query(data->if_index);
    734 #ifndef FEATURE_IPACM_HAL
    735 			/* add the check see if tether_iface is valid or not */
    736 			if (iface_ipa_index_query(data->if_index_tether) == INVALID_IFACE)
    737 			{
    738 				IPACMERR("UPSTREAM_ROUTE_ADD tether_if(%d), not valid ignore\n", INVALID_IFACE);
    739 				return;
    740 			}
    741 #endif
    742 			if (ipa_interface_index == ipa_if_num)
    743 			{
    744 				IPACMDBG_H("Received IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT (Android) for ip-type (%d)\n", data->iptype);
    745 				/* The special below condition is to handle default gateway */
    746 				if ((data->iptype == IPA_IP_v4) && (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX))
    747 				{
    748 					if (active_v4 == false)
    749 					{
    750 #ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN
    751 						IPACMDBG_H("adding routing table(upstream), dev (%s) ip-type(%d) default gw (%x)\n", dev_name,data->iptype, wan_v4_addr_gw);
    752 						wan_v4_addr_gw = data->ipv4_addr_gw;
    753 						wan_v4_addr_gw_set = true;
    754 						/* Check & construct STA header */
    755 						handle_sta_header_add_evt();
    756 #else
    757 						IPACMDBG_H("adding routing table(upstream), dev (%s) ip-type(%d)\n", dev_name,data->iptype);
    758 #endif
    759 						handle_route_add_evt(data->iptype); //sky
    760 					}
    761 #ifdef FEATURE_IPA_ANDROID
    762 #ifdef FEATURE_IPACM_HAL
    763 					post_wan_up_tether_evt(data->iptype, 0);
    764 #else
    765 					/* using ipa_if_index, not netdev_index */
    766 					post_wan_up_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether));
    767 #endif
    768 #endif
    769 				}
    770 				else if ((data->iptype == IPA_IP_v6) && (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX))
    771 				{
    772 					if(ipv6_prefix[0] == 0 && ipv6_prefix[1] == 0)
    773 					{
    774 						IPACMDBG_H("IPv6 default route comes earlier than global IP, ignore.\n");
    775 						return;
    776 					}
    777 
    778 					if (active_v6 == false)
    779 					{
    780 						IPACMDBG_H("\n get default v6 route (dst:00.00.00.00) upstream\n");
    781 #ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN
    782 						IPACMDBG_H(" IPV6 gateway: %08x:%08x:%08x:%08x \n",
    783 								data->ipv6_addr_gw[0], data->ipv6_addr_gw[1], data->ipv6_addr_gw[2], data->ipv6_addr_gw[3]);
    784 						wan_v6_addr_gw[0] = data->ipv6_addr_gw[0];
    785 						wan_v6_addr_gw[1] = data->ipv6_addr_gw[1];
    786 						wan_v6_addr_gw[2] = data->ipv6_addr_gw[2];
    787 						wan_v6_addr_gw[3] = data->ipv6_addr_gw[3];
    788 						wan_v6_addr_gw_set = true;
    789 						/* Check & construct STA header */
    790 						handle_sta_header_add_evt();
    791 #endif
    792 						handle_route_add_evt(data->iptype);
    793 					}
    794 #ifdef FEATURE_IPA_ANDROID
    795 #ifdef FEATURE_IPACM_HAL
    796 					post_wan_up_tether_evt(data->iptype, 0);
    797 #else
    798 					/* using ipa_if_index, not netdev_index */
    799 					post_wan_up_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether));
    800 #endif
    801 #endif
    802 				}
    803 			}
    804 			else /* double check if current default iface is not itself */
    805 			{
    806 				if ((data->iptype == IPA_IP_v4) && (active_v4 == true))
    807 				{
    808 					IPACMDBG_H("Received v4 IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
    809 					IPACMDBG_H("need clean default v4 route (dst:0.0.0.0) for old iface (%s)\n", dev_name);
    810 					wan_v4_addr_gw_set = false;
    811 					if(m_is_sta_mode == Q6_WAN)
    812 					{
    813 						del_wan_firewall_rule(IPA_IP_v4);
    814 						install_wan_filtering_rule(false);
    815 						handle_route_del_evt_ex(IPA_IP_v4);
    816 					}
    817 					else
    818 					{
    819 						del_dft_firewall_rules(IPA_IP_v4);
    820 						handle_route_del_evt(IPA_IP_v4);
    821 					}
    822 				}
    823 				else if ((data->iptype == IPA_IP_v6) && (active_v6 == true))
    824 				{
    825 				    IPACMDBG_H("Received v6 IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
    826 					IPACMDBG_H("need clean default v6 route for old iface (%s)\n", dev_name);
    827 					if(m_is_sta_mode == Q6_WAN)
    828 					{
    829 						del_wan_firewall_rule(IPA_IP_v6);
    830 						install_wan_filtering_rule(false);
    831 						handle_route_del_evt_ex(IPA_IP_v6);
    832 					}
    833 					else
    834 					{
    835 						del_dft_firewall_rules(IPA_IP_v6);
    836 						handle_route_del_evt(IPA_IP_v6);
    837 					}
    838 				}
    839 			}
    840 		}
    841 		break;
    842 
    843 	case IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT:
    844 		{
    845 			ipacm_event_data_iptype *data = (ipacm_event_data_iptype *)param;
    846 			ipa_interface_index = iface_ipa_index_query(data->if_index);
    847 #ifndef FEATURE_IPACM_HAL
    848 			/* add the check see if tether_iface is valid or not */
    849 			if (iface_ipa_index_query(data->if_index_tether) == INVALID_IFACE)
    850 			{
    851 				IPACMERR("UPSTREAM_ROUTE_DEL tether_if(%d), not valid ignore\n", INVALID_IFACE);
    852 				return;
    853 			}
    854 #endif
    855 			if (ipa_interface_index == ipa_if_num)
    856 			{
    857 				IPACMDBG_H("Received IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT\n");
    858 				if ((data->iptype == IPA_IP_v4) && (active_v4 == true))
    859 				{
    860 					IPACMDBG_H("get del default v4 route (dst:0.0.0.0)\n");
    861 					wan_v4_addr_gw_set = false;
    862 #ifdef FEATURE_IPA_ANDROID
    863 #ifdef FEATURE_IPACM_HAL
    864 					post_wan_down_tether_evt(data->iptype, 0);
    865 #else
    866 					/* using ipa_if_index, not netdev_index */
    867 					post_wan_down_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether));
    868 					/* no any ipv4 tether iface support*/
    869 					if(IPACM_Wan::ipa_if_num_tether_v4_total != 0)
    870 					{
    871 						IPACMDBG_H("still have tether ipv4 client on upsteam iface\n");
    872 						return;
    873 					}
    874 #endif
    875 #endif
    876 					if(m_is_sta_mode == Q6_WAN)
    877 					{
    878 						del_wan_firewall_rule(IPA_IP_v4);
    879 						install_wan_filtering_rule(false);
    880 						handle_route_del_evt_ex(IPA_IP_v4);
    881 					}
    882 					else
    883 					{
    884 						del_dft_firewall_rules(IPA_IP_v4);
    885 						handle_route_del_evt(IPA_IP_v4);
    886 					}
    887 				}
    888 				else if ((data->iptype == IPA_IP_v6) && (active_v6 == true))
    889 				{
    890 #ifdef FEATURE_IPA_ANDROID
    891 #ifdef FEATURE_IPACM_HAL
    892 					post_wan_down_tether_evt(data->iptype, 0);
    893 #else
    894 
    895 					/* using ipa_if_index, not netdev_index */
    896 					post_wan_down_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether));
    897 					/* no any ipv6 tether iface support*/
    898 					if(IPACM_Wan::ipa_if_num_tether_v6_total != 0)
    899 					{
    900 						IPACMDBG_H("still have tether ipv6 client on upsteam iface\n");
    901 						return;
    902 					}
    903 #endif
    904 #endif
    905 					if(m_is_sta_mode == Q6_WAN)
    906 					{
    907 						del_wan_firewall_rule(IPA_IP_v6);
    908 						install_wan_filtering_rule(false);
    909 						handle_route_del_evt_ex(IPA_IP_v6);
    910 					}
    911 					else
    912 					{
    913 						del_dft_firewall_rules(IPA_IP_v6);
    914 						handle_route_del_evt(IPA_IP_v6);
    915 					}
    916 				}
    917 			}
    918 		}
    919 		break;
    920 	case IPA_NETWORK_STATS_UPDATE_EVENT:
    921 		{
    922 			ipa_get_apn_data_stats_resp_msg_v01 *data = (ipa_get_apn_data_stats_resp_msg_v01 *)param;
    923 			if (!data->apn_data_stats_list_valid)
    924 			{
    925 				IPACMERR("not valid APN\n");
    926 				return;
    927 			}
    928 			else
    929 			{
    930 				handle_network_stats_update(data);
    931 			}
    932 		}
    933 		break;
    934 	case IPA_ROUTE_ADD_EVENT:
    935 		{
    936 			ipacm_event_data_addr *data = (ipacm_event_data_addr *)param;
    937 			ipa_interface_index = iface_ipa_index_query(data->if_index);
    938 			if (ipa_interface_index == ipa_if_num)
    939 			{
    940 				IPACMDBG_H("Received IPA_ROUTE_ADD_EVENT\n");
    941 				IPACMDBG_H("ipv4 addr 0x%x\n", data->ipv4_addr);
    942 				IPACMDBG_H("ipv4 addr mask 0x%x\n", data->ipv4_addr_mask);
    943 
    944 				/* The special below condition is to handle default gateway */
    945 				if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == false)
    946 					&& (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX))
    947 				{
    948 					wan_v4_addr_gw = data->ipv4_addr_gw;
    949 					wan_v4_addr_gw_set = true;
    950 					IPACMDBG_H("adding routing table, dev (%s) ip-type(%d), default gw (%x)\n", dev_name,data->iptype, wan_v4_addr_gw);
    951 					/* Check & construct STA header */
    952 					handle_sta_header_add_evt();
    953 					handle_route_add_evt(data->iptype);
    954 					/* Add IPv6 routing table if XLAT is enabled */
    955 					if(is_xlat && (m_is_sta_mode == Q6_WAN) && (active_v6 == false))
    956 					{
    957 						IPACMDBG_H("XLAT enabled: adding IPv6 routing table dev (%s)\n", dev_name);
    958 						handle_route_add_evt(IPA_IP_v6);
    959 					}
    960 				}
    961 				else if ((data->iptype == IPA_IP_v6) &&
    962 						(!data->ipv6_addr[0]) && (!data->ipv6_addr[1]) && (!data->ipv6_addr[2]) && (!data->ipv6_addr[3]) &&
    963 						(active_v6 == false) &&	(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX))
    964 				{
    965 					if(ipv6_prefix[0] == 0 && ipv6_prefix[1] == 0)
    966 					{
    967 						IPACMDBG_H("IPv6 default route comes earlier than global IP, ignore.\n");
    968 						return;
    969 					}
    970 
    971 					IPACMDBG_H("\n get default v6 route (dst:00.00.00.00)\n");
    972 					IPACMDBG_H(" IPV6 dst: %08x:%08x:%08x:%08x \n",
    973 							data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]);
    974 					IPACMDBG_H(" IPV6 gateway: %08x:%08x:%08x:%08x \n",
    975 							data->ipv6_addr_gw[0], data->ipv6_addr_gw[1], data->ipv6_addr_gw[2], data->ipv6_addr_gw[3]);
    976 					wan_v6_addr_gw[0] = data->ipv6_addr_gw[0];
    977 					wan_v6_addr_gw[1] = data->ipv6_addr_gw[1];
    978 					wan_v6_addr_gw[2] = data->ipv6_addr_gw[2];
    979 					wan_v6_addr_gw[3] = data->ipv6_addr_gw[3];
    980 					wan_v6_addr_gw_set = true;
    981 					/* Check & construct STA header */
    982 					handle_sta_header_add_evt();
    983 					handle_route_add_evt(data->iptype);
    984 				}
    985 			}
    986 			else /* double check if current default iface is not itself */
    987 			{
    988 				if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == true))
    989 				{
    990 					IPACMDBG_H("Received v4 IPA_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
    991 					IPACMDBG_H("ipv4 addr 0x%x\n", data->ipv4_addr);
    992 					IPACMDBG_H("ipv4 addr mask 0x%x\n", data->ipv4_addr_mask);
    993 					IPACMDBG_H("need clean default v4 route (dst:0.0.0.0) for old iface (%s)\n", dev_name);
    994 					wan_v4_addr_gw_set = false;
    995 					if(m_is_sta_mode == Q6_WAN)
    996 					{
    997 						del_wan_firewall_rule(IPA_IP_v4);
    998 						install_wan_filtering_rule(false);
    999 						handle_route_del_evt_ex(IPA_IP_v4);
   1000 					}
   1001 					else
   1002 					{
   1003 						del_dft_firewall_rules(IPA_IP_v4);
   1004 						handle_route_del_evt(IPA_IP_v4);
   1005 					}
   1006 				}
   1007 				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))
   1008 				{
   1009 				    IPACMDBG_H("Received v6 IPA_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
   1010 					IPACMDBG_H("need clean default v6 route for old iface (%s)\n", dev_name);
   1011 					if(m_is_sta_mode == Q6_WAN)
   1012 					{
   1013 						del_wan_firewall_rule(IPA_IP_v6);
   1014 						install_wan_filtering_rule(false);
   1015 						handle_route_del_evt_ex(IPA_IP_v6);
   1016 					}
   1017 					else
   1018 					{
   1019 						del_dft_firewall_rules(IPA_IP_v6);
   1020 						handle_route_del_evt(IPA_IP_v6);
   1021 					}
   1022 				}
   1023 			}
   1024 		}
   1025 		break;
   1026 
   1027 	case IPA_ROUTE_DEL_EVENT:
   1028 		{
   1029 			ipacm_event_data_addr *data = (ipacm_event_data_addr *)param;
   1030 			ipa_interface_index = iface_ipa_index_query(data->if_index);
   1031 			if (ipa_interface_index == ipa_if_num)
   1032 			{
   1033 				IPACMDBG_H("Received IPA_ROUTE_DEL_EVENT\n");
   1034 				if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == true))
   1035 				{
   1036 					IPACMDBG_H("get del default v4 route (dst:0.0.0.0)\n");
   1037 					wan_v4_addr_gw_set = false;
   1038 					if(m_is_sta_mode == Q6_WAN)
   1039 					{
   1040 						del_wan_firewall_rule(IPA_IP_v4);
   1041 						install_wan_filtering_rule(false);
   1042 						handle_route_del_evt_ex(IPA_IP_v4);
   1043 
   1044 						if(is_xlat && active_v6 == true)
   1045 						{
   1046 							IPACMDBG_H("XLAT enabled: Delete IPv6 routing table dev (%s)\n", dev_name);
   1047 							del_wan_firewall_rule(IPA_IP_v6);
   1048 							install_wan_filtering_rule(false);
   1049 							handle_route_del_evt_ex(IPA_IP_v6);
   1050 						}
   1051 					}
   1052 					else
   1053 					{
   1054 						del_dft_firewall_rules(IPA_IP_v4);
   1055 						handle_route_del_evt(IPA_IP_v4);
   1056 					}
   1057 				}
   1058 				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))
   1059 				{
   1060 
   1061 					IPACMDBG_H("get del default v6 route (dst:00.00.00.00)\n");
   1062 					if(m_is_sta_mode == Q6_WAN)
   1063 					{
   1064 						del_wan_firewall_rule(IPA_IP_v6);
   1065 						install_wan_filtering_rule(false);
   1066 						handle_route_del_evt_ex(IPA_IP_v6);
   1067 					}
   1068 					else
   1069 					{
   1070 						del_dft_firewall_rules(IPA_IP_v6);
   1071 						handle_route_del_evt(IPA_IP_v6);
   1072 					}
   1073 				}
   1074 			}
   1075 		}
   1076 		break;
   1077 
   1078 	case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT:
   1079 		{
   1080 			ipacm_event_data_all *data = (ipacm_event_data_all *)param;
   1081 			ipa_interface_index = iface_ipa_index_query(data->if_index);
   1082 
   1083 			if (ipa_interface_index == ipa_if_num)
   1084 			{
   1085 				IPACMDBG_H("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT in STA mode\n");
   1086 
   1087 				if (m_is_sta_mode == WLAN_WAN)
   1088 				{
   1089 					if (data->iptype == IPA_IP_v4 && data->ipv4_addr == wan_v4_addr)
   1090 					{
   1091 						IPACMDBG_H("Ignore IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT in STA mode\n");
   1092 						IPACMDBG_H("for its own ipv4 address\n");
   1093 						return;
   1094 					}
   1095 					else if (data->iptype == IPA_IP_v6)
   1096 					{
   1097 						for (uint32_t num_ipv6_addr = 0; num_ipv6_addr < num_dft_rt_v6; num_ipv6_addr++)
   1098 						{
   1099 							if ((ipv6_addr[num_ipv6_addr][0] == data->ipv6_addr[0]) &&
   1100 								(ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) &&
   1101 								(ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) &&
   1102 								(ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3]))
   1103 							{
   1104 								IPACMDBG_H("Ignore IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT in STA mode\n");
   1105 								IPACMDBG_H("for its own ipv6 address\n");
   1106 								return;
   1107 							}
   1108 						}
   1109 					}
   1110 				}
   1111 
   1112 				IPACMDBG_H("wan-iface got client \n");
   1113 				/* first construc WAN-client full header */
   1114 				if(memcmp(data->mac_addr,
   1115 						invalid_mac,
   1116 						sizeof(data->mac_addr)) == 0)
   1117 				{
   1118 					IPACMDBG_H("Received invalid Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
   1119 					 data->mac_addr[0], data->mac_addr[1], data->mac_addr[2],
   1120 					 data->mac_addr[3], data->mac_addr[4], data->mac_addr[5]);
   1121 					return;
   1122 				}
   1123 
   1124 				handle_wan_hdr_init(data->mac_addr);
   1125 				IPACMDBG_H("construct wan-client header and route rules \n");
   1126 				/* Associate with IP and construct RT-rule */
   1127 				if (handle_wan_client_ipaddr(data) == IPACM_FAILURE)
   1128 				{
   1129 					return;
   1130 				}
   1131 				handle_wan_client_route_rule(data->mac_addr, data->iptype);
   1132 				/* Check & construct STA header */
   1133 				handle_sta_header_add_evt();
   1134 				return;
   1135 			}
   1136 		}
   1137 		break;
   1138 
   1139 	case IPA_SW_ROUTING_ENABLE:
   1140 		IPACMDBG_H("Received IPA_SW_ROUTING_ENABLE\n");
   1141 		/* handle software routing enable event */
   1142 		if(m_is_sta_mode == Q6_WAN)
   1143 		{
   1144 			install_wan_filtering_rule(true);
   1145 		}
   1146 		else
   1147 		{
   1148 			handle_software_routing_enable();
   1149 		}
   1150 		break;
   1151 
   1152 	case IPA_SW_ROUTING_DISABLE:
   1153 		IPACMDBG_H("Received IPA_SW_ROUTING_DISABLE\n");
   1154 		/* handle software routing disable event */
   1155 		if(m_is_sta_mode == Q6_WAN)
   1156 		{
   1157 			/* send current DL rules to modem */
   1158 			install_wan_filtering_rule(false);
   1159 			softwarerouting_act = false;
   1160 		}
   1161 		else
   1162 		{
   1163 			handle_software_routing_disable();
   1164 		}
   1165 		break;
   1166 
   1167 	case IPA_FIREWALL_CHANGE_EVENT:
   1168 		IPACMDBG_H("Received IPA_FIREWALL_CHANGE_EVENT\n");
   1169 
   1170 		if(m_is_sta_mode == Q6_WAN)
   1171 		{
   1172 			if(is_default_gateway == false)
   1173 			{
   1174 				IPACMDBG_H("Interface %s is not default gw, return.\n", dev_name);
   1175 				return;
   1176 			}
   1177 
   1178 			if(ip_type == IPA_IP_v4)
   1179 			{
   1180 				del_wan_firewall_rule(IPA_IP_v4);
   1181 				config_wan_firewall_rule(IPA_IP_v4);
   1182 				install_wan_filtering_rule(false);
   1183 			}
   1184 			else if(ip_type == IPA_IP_v6)
   1185 			{
   1186 				del_wan_firewall_rule(IPA_IP_v6);
   1187 				config_wan_firewall_rule(IPA_IP_v6);
   1188 				install_wan_filtering_rule(false);
   1189 			}
   1190 			else if(ip_type == IPA_IP_MAX)
   1191 			{
   1192 				del_wan_firewall_rule(IPA_IP_v4);
   1193 				config_wan_firewall_rule(IPA_IP_v4);
   1194 
   1195 				del_wan_firewall_rule(IPA_IP_v6);
   1196 				config_wan_firewall_rule(IPA_IP_v6);
   1197 				install_wan_filtering_rule(false);
   1198 			}
   1199 			else
   1200 			{
   1201 				IPACMERR("IP type is not expected.\n");
   1202 			}
   1203 		}
   1204 		else
   1205 		{
   1206 			if (active_v4)
   1207 			{
   1208 				del_dft_firewall_rules(IPA_IP_v4);
   1209 				config_dft_firewall_rules(IPA_IP_v4);
   1210 			}
   1211 			if (active_v6)
   1212 			{
   1213 
   1214 				del_dft_firewall_rules(IPA_IP_v6);
   1215 				config_dft_firewall_rules(IPA_IP_v6);
   1216 			}
   1217 		}
   1218 		break;
   1219 
   1220 		case IPA_WLAN_SWITCH_TO_SCC:
   1221 			if(IPACM_Wan::backhaul_is_sta_mode == true)
   1222 			{
   1223 				IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_SCC\n");
   1224 				if(ip_type == IPA_IP_MAX)
   1225 				{
   1226 					handle_wlan_SCC_MCC_switch(true, IPA_IP_v4);
   1227 					handle_wlan_SCC_MCC_switch(true, IPA_IP_v6);
   1228 					handle_wan_client_SCC_MCC_switch(true, IPA_IP_v4);
   1229 					handle_wan_client_SCC_MCC_switch(true, IPA_IP_v6);
   1230 				}
   1231 				else
   1232 				{
   1233 					handle_wlan_SCC_MCC_switch(true, ip_type);
   1234 					handle_wan_client_SCC_MCC_switch(true, ip_type);
   1235 				}
   1236 			}
   1237 			break;
   1238 
   1239 		case IPA_WLAN_SWITCH_TO_MCC:
   1240 			if(IPACM_Wan::backhaul_is_sta_mode == true)
   1241 			{
   1242 				IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_MCC\n");
   1243 				if(ip_type == IPA_IP_MAX)
   1244 				{
   1245 					handle_wlan_SCC_MCC_switch(false, IPA_IP_v4);
   1246 					handle_wlan_SCC_MCC_switch(false, IPA_IP_v6);
   1247 					handle_wan_client_SCC_MCC_switch(false, IPA_IP_v4);
   1248 					handle_wan_client_SCC_MCC_switch(false, IPA_IP_v6);
   1249 				}
   1250 				else
   1251 				{
   1252 					handle_wlan_SCC_MCC_switch(false, ip_type);
   1253 					handle_wan_client_SCC_MCC_switch(false, ip_type);
   1254 				}
   1255 			}
   1256 			break;
   1257 
   1258 	default:
   1259 		break;
   1260 	}
   1261 
   1262 	return;
   1263 }
   1264 
   1265 /* wan default route/filter rule configuration */
   1266 int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype)
   1267 {
   1268 
   1269 	/* add default WAN route */
   1270 	struct ipa_ioc_add_rt_rule *rt_rule = NULL;
   1271 	struct ipa_rt_rule_add *rt_rule_entry;
   1272 	uint32_t tx_index = 0;
   1273 	const int NUM = 1;
   1274 	ipacm_cmd_q_data evt_data;
   1275 	struct ipa_ioc_get_hdr hdr;
   1276 
   1277 	IPACMDBG_H("ip-type:%d\n", iptype);
   1278 
   1279 	/* copy header from tx-property, see if partial or not */
   1280 	/* assume all tx-property uses the same header name for v4 or v6*/
   1281 
   1282 	if(tx_prop == NULL)
   1283 	{
   1284 		IPACMDBG_H("No tx properties, ignore default route setting\n");
   1285 		return IPACM_SUCCESS;
   1286 	}
   1287 
   1288 	is_default_gateway = true;
   1289 	IPACMDBG_H("Default route is added to iface %s.\n", dev_name);
   1290 
   1291 	if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == BRIDGE)
   1292 	{
   1293 		IPACM_Wan::backhaul_is_wan_bridge = true;
   1294 	}
   1295 	else
   1296 	{
   1297 		IPACM_Wan::backhaul_is_wan_bridge = false;
   1298 	}
   1299 	IPACMDBG_H("backhaul_is_wan_bridge ?: %d \n", IPACM_Wan::backhaul_is_wan_bridge);
   1300 
   1301 	if (m_is_sta_mode !=Q6_WAN)
   1302 	{
   1303 		IPACM_Wan::backhaul_is_sta_mode	= true;
   1304 		if((iptype==IPA_IP_v4) && (header_set_v4 != true))
   1305 		{
   1306 			header_partial_default_wan_v4 = true;
   1307 			IPACMDBG_H("STA ipv4-header haven't constructed \n");
   1308 			return IPACM_SUCCESS;
   1309 		}
   1310 		else if((iptype==IPA_IP_v6) && (header_set_v6 != true))
   1311 		{
   1312 			header_partial_default_wan_v6 = true;
   1313 			IPACMDBG_H("STA ipv6-header haven't constructed \n");
   1314 			return IPACM_SUCCESS;
   1315 		}
   1316 	}
   1317 	else
   1318 	{
   1319 		IPACM_Wan::backhaul_is_sta_mode	= false;
   1320 		IPACMDBG_H("reset backhaul to LTE \n");
   1321 
   1322 		if (iface_query != NULL && iface_query->num_ext_props > 0)
   1323 		{
   1324 			if(ext_prop == NULL)
   1325 			{
   1326 				IPACMERR("Extended property is empty.\n");
   1327 				return IPACM_FAILURE;
   1328 			}
   1329 			else
   1330 			{
   1331 				IPACM_Iface::ipacmcfg->SetQmapId(ext_prop->ext[0].mux_id);
   1332 				IPACMDBG_H("Setting up QMAP ID %d.\n", ext_prop->ext[0].mux_id);
   1333 			}
   1334 		}
   1335 		else
   1336 		{
   1337 			IPACMERR("iface_query is empty.\n");
   1338 			return IPACM_FAILURE;
   1339 		}
   1340 	}
   1341 #if 0
   1342     for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
   1343 	{
   1344 		if(tx_prop->tx[cnt].ip==iptype)
   1345 		break;
   1346 	}
   1347 
   1348 	if(tx_prop->tx[cnt].hdr_name != NULL)
   1349 	{
   1350 	    memset(&sCopyHeader, 0, sizeof(sCopyHeader));
   1351 	    memcpy(sCopyHeader.name,
   1352 	    			 tx_prop->tx[cnt].hdr_name,
   1353 	    			 sizeof(sCopyHeader.name));
   1354 
   1355 	    IPACMDBG_H("header name: %s\n", sCopyHeader.name);
   1356 	    if (m_header.CopyHeader(&sCopyHeader) == false)
   1357 	    {
   1358 	    	IPACMERR("ioctl copy header failed");
   1359 	    	return IPACM_FAILURE;
   1360 	    }
   1361 	    IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
   1362 	    if(sCopyHeader.is_partial)
   1363 	    {
   1364  	        IPACMDBG_H("Not setup default WAN routing rules cuz the header is not complete\n");
   1365             if(iptype==IPA_IP_v4)
   1366 			{
   1367 				header_partial_default_wan_v4 = true;
   1368             }
   1369 			else
   1370 			{
   1371 				header_partial_default_wan_v6 = true;
   1372 			}
   1373 			return IPACM_SUCCESS;
   1374 	    }
   1375 	    else
   1376 	    {
   1377             if(iptype==IPA_IP_v4)
   1378 			{
   1379 				header_partial_default_wan_v4 = false;
   1380             }
   1381 			else
   1382 			{
   1383 				header_partial_default_wan_v6 = false;
   1384 			}
   1385 	    }
   1386     }
   1387 #endif
   1388 
   1389 	rt_rule = (struct ipa_ioc_add_rt_rule *)
   1390 		 calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
   1391 						NUM * sizeof(struct ipa_rt_rule_add));
   1392 
   1393 	if (!rt_rule)
   1394 	{
   1395 		IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n");
   1396 		return IPACM_FAILURE;
   1397 	}
   1398 
   1399 	rt_rule->commit = 1;
   1400 	rt_rule->num_rules = (uint8_t)NUM;
   1401 	rt_rule->ip = iptype;
   1402 
   1403 
   1404 	IPACMDBG_H(" WAN table created %s \n", rt_rule->rt_tbl_name);
   1405 	rt_rule_entry = &rt_rule->rules[0];
   1406 	rt_rule_entry->at_rear = true;
   1407 
   1408 	if(m_is_sta_mode != Q6_WAN)
   1409 	{
   1410 		IPACMDBG_H(" WAN instance is in STA mode \n");
   1411 		for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
   1412 		{
   1413 			if(iptype != tx_prop->tx[tx_index].ip)
   1414 			{
   1415 				IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n",
   1416 									tx_index, tx_prop->tx[tx_index].ip,iptype);
   1417 				continue;
   1418 			}
   1419 
   1420 			/* use the STA-header handler */
   1421 			if (iptype == IPA_IP_v4)
   1422 			{
   1423 				strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name, sizeof(rt_rule->rt_tbl_name));
   1424 				rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v4;
   1425 			}
   1426 			else
   1427 			{
   1428 				strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name));
   1429 				rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v6;
   1430 			}
   1431 
   1432 			if(IPACM_Iface::ipacmcfg->isMCC_Mode == true)
   1433 			{
   1434 				IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
   1435 						tx_prop->tx[tx_index].alt_dst_pipe);
   1436 				rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
   1437 			}
   1438 			else
   1439 			{
   1440 				rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
   1441 			}
   1442 			memcpy(&rt_rule_entry->rule.attrib,
   1443 						 &tx_prop->tx[tx_index].attrib,
   1444 						 sizeof(rt_rule_entry->rule.attrib));
   1445 
   1446 			rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   1447 			if (iptype == IPA_IP_v4)
   1448 			{
   1449 				rt_rule_entry->rule.attrib.u.v4.dst_addr      = 0;
   1450 				rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0;
   1451 #ifdef FEATURE_IPA_V3
   1452 
   1453 				rt_rule_entry->rule.hashable = true;
   1454 #endif
   1455 				if (false == m_routing.AddRoutingRule(rt_rule))
   1456 				{
   1457 		    		IPACMERR("Routing rule addition failed!\n");
   1458 		    		free(rt_rule);
   1459 		    		return IPACM_FAILURE;
   1460 				}
   1461 				wan_route_rule_v4_hdl[tx_index] = rt_rule_entry->rt_rule_hdl;
   1462 				IPACMDBG_H("Got ipv4 wan-route rule hdl:0x%x,tx:%d,ip-type: %d \n",
   1463 							 wan_route_rule_v4_hdl[tx_index],
   1464 							 tx_index,
   1465 							 iptype);
   1466 			}
   1467 			else
   1468 			{
   1469 				rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0;
   1470 				rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0;
   1471 				rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0;
   1472 				rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0;
   1473 				rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0;
   1474 				rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0;
   1475 				rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0;
   1476 				rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0;
   1477 #ifdef FEATURE_IPA_V3
   1478 				rt_rule_entry->rule.hashable = true;
   1479 #endif
   1480 				if (false == m_routing.AddRoutingRule(rt_rule))
   1481 				{
   1482 		    		IPACMERR("Routing rule addition failed!\n");
   1483 		    		free(rt_rule);
   1484 		    		return IPACM_FAILURE;
   1485 				}
   1486 				wan_route_rule_v6_hdl[tx_index] = rt_rule_entry->rt_rule_hdl;
   1487 				IPACMDBG_H("Set ipv6 wan-route rule hdl for v6_lan_table:0x%x,tx:%d,ip-type: %d \n",
   1488 							 wan_route_rule_v6_hdl[tx_index],
   1489 							 tx_index,
   1490 							 iptype);
   1491 			}
   1492 		}
   1493 	}
   1494 
   1495 	/* add a catch-all rule in wan dl routing table */
   1496 
   1497 	if (iptype == IPA_IP_v6)
   1498 	{
   1499 		strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name));
   1500 		memset(rt_rule_entry, 0, sizeof(struct ipa_rt_rule_add));
   1501 		rt_rule_entry->at_rear = true;
   1502 		if(m_is_sta_mode == Q6_WAN)
   1503 		{
   1504 			memset(&hdr, 0, sizeof(hdr));
   1505 			strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
   1506 			hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   1507 			if(m_header.GetHeaderHandle(&hdr) == false)
   1508 			{
   1509 				IPACMERR("Failed to get QMAP header.\n");
   1510 				return IPACM_FAILURE;
   1511 			}
   1512 			rt_rule_entry->rule.hdr_hdl = hdr.hdl;
   1513 			rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS;
   1514 		}
   1515 		else
   1516 		{
   1517 			/* create dummy ethernet header for v6 RX path */
   1518 			IPACMDBG_H("Construct dummy ethernet_header\n");
   1519 			if (add_dummy_rx_hdr())
   1520 			{
   1521 				IPACMERR("Construct dummy ethernet_header failed!\n");
   1522 				free(rt_rule);
   1523 				return IPACM_FAILURE;
   1524 			}
   1525 			rt_rule_entry->rule.hdr_proc_ctx_hdl = hdr_proc_hdl_dummy_v6;
   1526 			rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS;
   1527 		}
   1528 		rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
   1529 		rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0;
   1530 		rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0;
   1531 		rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0;
   1532 		rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0;
   1533 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0;
   1534 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0;
   1535 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0;
   1536 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0;
   1537 #ifdef FEATURE_IPA_V3
   1538 		rt_rule_entry->rule.hashable = true;
   1539 #endif
   1540 		if (false == m_routing.AddRoutingRule(rt_rule))
   1541 		{
   1542 			IPACMERR("Routing rule addition failed!\n");
   1543 			free(rt_rule);
   1544 			return IPACM_FAILURE;
   1545 		}
   1546 		wan_route_rule_v6_hdl_a5[0] = rt_rule_entry->rt_rule_hdl;
   1547 		IPACMDBG_H("Set ipv6 wan-route rule hdl for v6_wan_table:0x%x,tx:%d,ip-type: %d \n",
   1548 				wan_route_rule_v6_hdl_a5[0], 0, iptype);
   1549 	}
   1550 
   1551 	ipacm_event_iface_up *wanup_data;
   1552 	wanup_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up));
   1553 	if (wanup_data == NULL)
   1554 	{
   1555 		IPACMERR("Unable to allocate memory\n");
   1556 		free(rt_rule);
   1557 		return IPACM_FAILURE;
   1558 	}
   1559 	memset(wanup_data, 0, sizeof(ipacm_event_iface_up));
   1560 
   1561 	if (iptype == IPA_IP_v4)
   1562 	{
   1563 		IPACM_Wan::wan_up = true;
   1564 		active_v4 = true;
   1565 		memcpy(IPACM_Wan::wan_up_dev_name,
   1566 			dev_name,
   1567 				sizeof(IPACM_Wan::wan_up_dev_name));
   1568 
   1569 		if(m_is_sta_mode == Q6_WAN)
   1570 		{
   1571 			config_wan_firewall_rule(IPA_IP_v4);
   1572 			install_wan_filtering_rule(false);
   1573 		}
   1574 		else
   1575 		{
   1576 			config_dft_firewall_rules(IPA_IP_v4);
   1577 		}
   1578 
   1579 		memcpy(wanup_data->ifname, dev_name, sizeof(wanup_data->ifname));
   1580 		wanup_data->ipv4_addr = wan_v4_addr;
   1581 		if (m_is_sta_mode!=Q6_WAN)
   1582 		{
   1583 			wanup_data->is_sta = true;
   1584 		}
   1585 		else
   1586 		{
   1587 			wanup_data->is_sta = false;
   1588 		}
   1589 		IPACMDBG_H("Posting IPA_HANDLE_WAN_UP with below information:\n");
   1590 		IPACMDBG_H("if_name:%s, ipv4_address:0x%x, is sta mode:%d\n",
   1591 				wanup_data->ifname, wanup_data->ipv4_addr, wanup_data->is_sta);
   1592 		memset(&evt_data, 0, sizeof(evt_data));
   1593 
   1594 		/* send xlat configuration for installing uplink rules */
   1595 		if(is_xlat && (m_is_sta_mode == Q6_WAN))
   1596 		{
   1597 			IPACM_Wan::xlat_mux_id = ext_prop->ext[0].mux_id;
   1598 			wanup_data->xlat_mux_id = IPACM_Wan::xlat_mux_id;
   1599 			IPACMDBG_H("Set xlat configuraiton with below information:\n");
   1600 			IPACMDBG_H("xlat_enabled: %d xlat_mux_id: %d \n",
   1601 					is_xlat, xlat_mux_id);
   1602 		}
   1603 		else
   1604 		{
   1605 			IPACM_Wan::xlat_mux_id = 0;
   1606 			wanup_data->xlat_mux_id = 0;
   1607 			IPACMDBG_H("No xlat configuratio:\n");
   1608 		}
   1609 		evt_data.event = IPA_HANDLE_WAN_UP;
   1610 		evt_data.evt_data = (void *)wanup_data;
   1611 		IPACM_EvtDispatcher::PostEvt(&evt_data);
   1612 	}
   1613 	else
   1614 	{
   1615 		memcpy(backhaul_ipv6_prefix, ipv6_prefix, sizeof(backhaul_ipv6_prefix));
   1616 		IPACMDBG_H("Setup backhaul ipv6 prefix to be 0x%08x%08x.\n", backhaul_ipv6_prefix[0], backhaul_ipv6_prefix[1]);
   1617 
   1618 		IPACM_Wan::wan_up_v6 = true;
   1619 		active_v6 = true;
   1620 		memcpy(IPACM_Wan::wan_up_dev_name,
   1621 			dev_name,
   1622 				sizeof(IPACM_Wan::wan_up_dev_name));
   1623 
   1624 		if(m_is_sta_mode == Q6_WAN)
   1625 		{
   1626 			config_wan_firewall_rule(IPA_IP_v6);
   1627 			install_wan_filtering_rule(false);
   1628 		}
   1629 		else
   1630 		{
   1631 			config_dft_firewall_rules(IPA_IP_v6);
   1632 		}
   1633 
   1634 		memcpy(wanup_data->ifname, dev_name, sizeof(wanup_data->ifname));
   1635 		if (m_is_sta_mode!=Q6_WAN)
   1636 		{
   1637 			wanup_data->is_sta = true;
   1638 		}
   1639 		else
   1640 		{
   1641 			wanup_data->is_sta = false;
   1642 		}
   1643 		memcpy(wanup_data->ipv6_prefix, ipv6_prefix, sizeof(wanup_data->ipv6_prefix));
   1644 		IPACMDBG_H("Posting IPA_HANDLE_WAN_UP_V6 with below information:\n");
   1645 		IPACMDBG_H("if_name:%s, is sta mode: %d\n", wanup_data->ifname, wanup_data->is_sta);
   1646 		IPACMDBG_H("ipv6 prefix: 0x%08x%08x.\n", ipv6_prefix[0], ipv6_prefix[1]);
   1647 		memset(&evt_data, 0, sizeof(evt_data));
   1648 		evt_data.event = IPA_HANDLE_WAN_UP_V6;
   1649 		evt_data.evt_data = (void *)wanup_data;
   1650 		IPACM_EvtDispatcher::PostEvt(&evt_data);
   1651 	}
   1652 
   1653 	/* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */
   1654 	IPACMDBG_H("dev %s add producer dependency\n", dev_name);
   1655 	IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
   1656 	IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false);
   1657 
   1658 	if(rt_rule != NULL)
   1659 	{
   1660 		free(rt_rule);
   1661 	}
   1662 	return IPACM_SUCCESS;
   1663 }
   1664 
   1665 #ifdef FEATURE_IPA_ANDROID
   1666 /* wan default route/filter rule configuration */
   1667 int IPACM_Wan::post_wan_up_tether_evt(ipa_ip_type iptype, int ipa_if_num_tether)
   1668 {
   1669 	ipacm_cmd_q_data evt_data;
   1670 	ipacm_event_iface_up_tehter *wanup_data;
   1671 
   1672 	wanup_data = (ipacm_event_iface_up_tehter *)malloc(sizeof(ipacm_event_iface_up_tehter));
   1673 	if (wanup_data == NULL)
   1674 	{
   1675 		IPACMERR("Unable to allocate memory\n");
   1676 		return IPACM_FAILURE;
   1677 	}
   1678 	memset(wanup_data, 0, sizeof(ipacm_event_iface_up_tehter));
   1679 
   1680 	wanup_data->if_index_tether = ipa_if_num_tether;
   1681 	if (m_is_sta_mode!=Q6_WAN)
   1682 	{
   1683 		wanup_data->is_sta = true;
   1684 	}
   1685 	else
   1686 	{
   1687 		wanup_data->is_sta = false;
   1688 	}
   1689 	IPACMDBG_H("Posting IPA_HANDLE_WAN_UP_TETHER with below information:\n");
   1690 	IPACMDBG_H("tether_if_name:%s, is sta mode:%d\n",
   1691 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, wanup_data->is_sta);
   1692 	memset(&evt_data, 0, sizeof(evt_data));
   1693 
   1694 	if (iptype == IPA_IP_v4)
   1695 	{
   1696 		evt_data.event = IPA_HANDLE_WAN_UP_TETHER;
   1697 		/* Add support tether ifaces to its array*/
   1698 		IPACM_Wan::ipa_if_num_tether_v4[IPACM_Wan::ipa_if_num_tether_v4_total] = ipa_if_num_tether;
   1699 		IPACMDBG_H("adding tether iface(%s) ipa_if_num_tether_v4_total(%d) on wan_iface(%s)\n",
   1700 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name,
   1701 			IPACM_Wan::ipa_if_num_tether_v4_total,
   1702 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name);
   1703 		IPACM_Wan::ipa_if_num_tether_v4_total++;
   1704 	}
   1705 	else
   1706 	{
   1707 		evt_data.event = IPA_HANDLE_WAN_UP_V6_TETHER;
   1708 		memcpy(wanup_data->ipv6_prefix, ipv6_prefix, sizeof(wanup_data->ipv6_prefix));
   1709 		/* Add support tether ifaces to its array*/
   1710 		IPACM_Wan::ipa_if_num_tether_v6[IPACM_Wan::ipa_if_num_tether_v6_total] = ipa_if_num_tether;
   1711 		IPACMDBG_H("adding tether iface(%s) ipa_if_num_tether_v6_total(%d) on wan_iface(%s)\n",
   1712 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name,
   1713 			IPACM_Wan::ipa_if_num_tether_v6_total,
   1714 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name);
   1715 		IPACM_Wan::ipa_if_num_tether_v6_total++;
   1716 	}
   1717 		evt_data.evt_data = (void *)wanup_data;
   1718 		IPACM_EvtDispatcher::PostEvt(&evt_data);
   1719 
   1720 	return IPACM_SUCCESS;
   1721 }
   1722 
   1723 /* wan default route/filter rule configuration */
   1724 int IPACM_Wan::post_wan_down_tether_evt(ipa_ip_type iptype, int ipa_if_num_tether)
   1725 {
   1726 	ipacm_cmd_q_data evt_data;
   1727 	ipacm_event_iface_up_tehter *wandown_data;
   1728 	uint32_t i, j;
   1729 
   1730 	wandown_data = (ipacm_event_iface_up_tehter *)malloc(sizeof(ipacm_event_iface_up_tehter));
   1731 	if (wandown_data == NULL)
   1732 	{
   1733 		IPACMERR("Unable to allocate memory\n");
   1734 		return IPACM_FAILURE;
   1735 	}
   1736 	memset(wandown_data, 0, sizeof(ipacm_event_iface_up_tehter));
   1737 
   1738 	wandown_data->if_index_tether = ipa_if_num_tether;
   1739 	if (m_is_sta_mode!=Q6_WAN)
   1740 	{
   1741 		wandown_data->is_sta = true;
   1742 	}
   1743 	else
   1744 	{
   1745 		wandown_data->is_sta = false;
   1746 	}
   1747 	IPACMDBG_H("Posting IPA_HANDLE_WAN_DOWN_TETHER with below information:\n");
   1748 	IPACMDBG_H("tether_if_name:%s, is sta mode:%d\n",
   1749 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, wandown_data->is_sta);
   1750 	memset(&evt_data, 0, sizeof(evt_data));
   1751 
   1752 	if (iptype == IPA_IP_v4)
   1753 	{
   1754 		evt_data.event = IPA_HANDLE_WAN_DOWN_TETHER;
   1755 		/* delete support tether ifaces to its array*/
   1756 		for (i=0; i < IPACM_Wan::ipa_if_num_tether_v4_total; i++)
   1757 		{
   1758 			if(IPACM_Wan::ipa_if_num_tether_v4[i] == ipa_if_num_tether)
   1759 			{
   1760 				IPACMDBG_H("Found tether client at position %d name(%s)\n", i,
   1761 				IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name);
   1762 				break;
   1763 			}
   1764 		}
   1765 		if(i == IPACM_Wan::ipa_if_num_tether_v4_total)
   1766 		{
   1767 			IPACMDBG_H("Not finding the tether client.\n");
   1768 			free(wandown_data);
   1769 			return IPACM_SUCCESS;
   1770 		}
   1771 		for(j = i+1; j < IPACM_Wan::ipa_if_num_tether_v4_total; j++)
   1772 		{
   1773 			IPACM_Wan::ipa_if_num_tether_v4[j-1] = IPACM_Wan::ipa_if_num_tether_v4[j];
   1774 		}
   1775 		IPACM_Wan::ipa_if_num_tether_v4_total--;
   1776 		IPACMDBG_H("Now the total num of ipa_if_num_tether_v4_total is %d on wan-iface(%s)\n",
   1777 			IPACM_Wan::ipa_if_num_tether_v4_total,
   1778 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name);
   1779 	}
   1780 	else
   1781 	{
   1782 		evt_data.event = IPA_HANDLE_WAN_DOWN_V6_TETHER;
   1783 		/* delete support tether ifaces to its array*/
   1784 		for (i=0; i < IPACM_Wan::ipa_if_num_tether_v6_total; i++)
   1785 		{
   1786 			if(IPACM_Wan::ipa_if_num_tether_v6[i] == ipa_if_num_tether)
   1787 			{
   1788 				IPACMDBG_H("Found tether client at position %d name(%s)\n", i,
   1789 				IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name);
   1790 				break;
   1791 			}
   1792 		}
   1793 		if(i == IPACM_Wan::ipa_if_num_tether_v6_total)
   1794 		{
   1795 			IPACMDBG_H("Not finding the tether client.\n");
   1796 			free(wandown_data);
   1797 			return IPACM_SUCCESS;
   1798 		}
   1799 		for(j = i+1; j < IPACM_Wan::ipa_if_num_tether_v6_total; j++)
   1800 		{
   1801 			IPACM_Wan::ipa_if_num_tether_v6[j-1] = IPACM_Wan::ipa_if_num_tether_v6[j];
   1802 		}
   1803 		IPACM_Wan::ipa_if_num_tether_v6_total--;
   1804 		IPACMDBG_H("Now the total num of ipa_if_num_tether_v6_total is %d on wan-iface(%s)\n",
   1805 			IPACM_Wan::ipa_if_num_tether_v6_total,
   1806 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name);
   1807 	}
   1808 		evt_data.evt_data = (void *)wandown_data;
   1809 		IPACM_EvtDispatcher::PostEvt(&evt_data);
   1810 	return IPACM_SUCCESS;
   1811 }
   1812 #endif
   1813 
   1814 /* construct complete ethernet header */
   1815 int IPACM_Wan::handle_sta_header_add_evt()
   1816 {
   1817 	int res = IPACM_SUCCESS, index = IPACM_INVALID_INDEX;
   1818 	if((header_set_v4 == true) || (header_set_v6 == true))
   1819 	{
   1820 		IPACMDBG_H("Already add STA full header\n");
   1821 		return IPACM_SUCCESS;
   1822 	}
   1823 
   1824 	/* checking if the ipv4 same as default route */
   1825 	if(wan_v4_addr_gw_set)
   1826 	{
   1827 		index = get_wan_client_index_ipv4(wan_v4_addr_gw);
   1828 		if (index != IPACM_INVALID_INDEX)
   1829 		{
   1830 			IPACMDBG_H("Matched client index: %d\n", index);
   1831 			IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
   1832 					 get_client_memptr(wan_client, index)->mac[0],
   1833 					 get_client_memptr(wan_client, index)->mac[1],
   1834 					 get_client_memptr(wan_client, index)->mac[2],
   1835 					 get_client_memptr(wan_client, index)->mac[3],
   1836 					 get_client_memptr(wan_client, index)->mac[4],
   1837 					 get_client_memptr(wan_client, index)->mac[5]);
   1838 
   1839 			if(get_client_memptr(wan_client, index)->ipv4_header_set)
   1840 			{
   1841 				hdr_hdl_sta_v4 = get_client_memptr(wan_client, index)->hdr_hdl_v4;
   1842 				header_set_v4 = true;
   1843 				IPACMDBG_H("add full ipv4 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v4);
   1844 				/* store external_ap's MAC */
   1845 				memcpy(ext_router_mac_addr, get_client_memptr(wan_client, index)->mac, sizeof(ext_router_mac_addr));
   1846 			}
   1847 			else
   1848 			{
   1849 				IPACMERR(" wan-client got ipv4 however didn't construct complete ipv4 header \n");
   1850 				return IPACM_FAILURE;
   1851 			}
   1852 
   1853 			if(get_client_memptr(wan_client, index)->ipv6_header_set)
   1854 			{
   1855 				hdr_hdl_sta_v6 = get_client_memptr(wan_client, index)->hdr_hdl_v6;
   1856 				header_set_v6 = true;
   1857 				IPACMDBG_H("add full ipv6 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v6);
   1858 			}
   1859 			else
   1860 			{
   1861 				IPACMERR(" wan-client got ipv6 however didn't construct complete ipv6 header \n");
   1862 				return IPACM_FAILURE;
   1863 			}
   1864 		}
   1865 		else
   1866 		{
   1867 			IPACMDBG_H(" currently can't find matched wan-client's MAC-addr, waiting for header construction\n");
   1868 			return IPACM_SUCCESS;
   1869 		}
   1870 	}
   1871 
   1872 	/* checking if the ipv4 same as default route */
   1873 	if(wan_v6_addr_gw_set)
   1874 	{
   1875 		index = get_wan_client_index_ipv6(wan_v6_addr_gw);
   1876 		if (index != IPACM_INVALID_INDEX)
   1877 		{
   1878 			IPACMDBG_H("Matched client index: %d\n", index);
   1879 			IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
   1880 					 get_client_memptr(wan_client, index)->mac[0],
   1881 					 get_client_memptr(wan_client, index)->mac[1],
   1882 					 get_client_memptr(wan_client, index)->mac[2],
   1883 					 get_client_memptr(wan_client, index)->mac[3],
   1884 					 get_client_memptr(wan_client, index)->mac[4],
   1885 					 get_client_memptr(wan_client, index)->mac[5]);
   1886 
   1887 			if(get_client_memptr(wan_client, index)->ipv6_header_set)
   1888 			{
   1889 				hdr_hdl_sta_v6 = get_client_memptr(wan_client, index)->hdr_hdl_v6;
   1890 				header_set_v6 = true;
   1891 				IPACMDBG_H("add full ipv6 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v6);
   1892 				/* store external_ap's MAC */
   1893 				memcpy(ext_router_mac_addr, get_client_memptr(wan_client, index)->mac, sizeof(ext_router_mac_addr));
   1894 			}
   1895 			else
   1896 			{
   1897 				IPACMERR(" wan-client got ipv6 however didn't construct complete ipv4 header \n");
   1898 				return IPACM_FAILURE;
   1899 			}
   1900 
   1901 			if(get_client_memptr(wan_client, index)->ipv4_header_set)
   1902 			{
   1903 				hdr_hdl_sta_v4 = get_client_memptr(wan_client, index)->hdr_hdl_v4;
   1904 				header_set_v4 = true;
   1905 				IPACMDBG_H("add full ipv4 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v4);
   1906 			}
   1907 			else
   1908 			{
   1909 				IPACMERR(" wan-client got ipv4 however didn't construct complete ipv4 header \n");
   1910 				return IPACM_FAILURE;
   1911 			}
   1912 		}
   1913 		else
   1914 		{
   1915 			IPACMDBG_H(" currently can't find matched wan-client's MAC-addr, waiting for header construction\n");
   1916 			return IPACM_SUCCESS;
   1917 		}
   1918 	}
   1919 
   1920 	/* see if default routes are setup before constructing full header */
   1921 	if(header_partial_default_wan_v4 == true)
   1922 	{
   1923 	   handle_route_add_evt(IPA_IP_v4);
   1924 	}
   1925 
   1926 	if(header_partial_default_wan_v6 == true)
   1927 	{
   1928 	   handle_route_add_evt(IPA_IP_v6);
   1929 	}
   1930 	return res;
   1931 }
   1932 
   1933 /* For checking attribute mask field in firewall rules for IPv6 only */
   1934 bool IPACM_Wan::check_dft_firewall_rules_attr_mask(IPACM_firewall_conf_t *firewall_config)
   1935 {
   1936 	uint32_t attrib_mask = 0ul;
   1937 	attrib_mask =	IPA_FLT_SRC_PORT_RANGE |
   1938 			IPA_FLT_DST_PORT_RANGE |
   1939 			IPA_FLT_TYPE |
   1940 			IPA_FLT_CODE |
   1941 			IPA_FLT_SPI |
   1942 			IPA_FLT_SRC_PORT |
   1943 			IPA_FLT_DST_PORT;
   1944 
   1945 	for (int i = 0; i < firewall_config->num_extd_firewall_entries; i++)
   1946 	{
   1947 		if (firewall_config->extd_firewall_entries[i].ip_vsn == 6)
   1948 		{
   1949 			if (firewall_config->extd_firewall_entries[i].attrib.attrib_mask & attrib_mask)
   1950 			{
   1951 				IPACMDBG_H("IHL based attribute mask is found: install IPv6 frag firewall rule \n");
   1952 				return true;
   1953 			}
   1954 		}
   1955 	}
   1956 	IPACMDBG_H("IHL based attribute mask is not found: no IPv6 frag firewall rule \n");
   1957 	return false;
   1958 }
   1959 
   1960 /* for STA mode: add firewall rules */
   1961 int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype)
   1962 {
   1963 	struct ipa_flt_rule_add flt_rule_entry;
   1964 	int i, rule_v4 = 0, rule_v6 = 0, len;
   1965 
   1966 	IPACMDBG_H("ip-family: %d; \n", iptype);
   1967 
   1968 	if (rx_prop == NULL)
   1969 	{
   1970 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
   1971 		return IPACM_SUCCESS;
   1972 	}
   1973 
   1974 	/* default firewall is disable and the rule action is drop */
   1975 	memset(&firewall_config, 0, sizeof(firewall_config));
   1976 	strlcpy(firewall_config.firewall_config_file, "/etc/mobileap_firewall.xml", sizeof(firewall_config.firewall_config_file));
   1977 
   1978 	IPACMDBG_H("Firewall XML file is %s \n", firewall_config.firewall_config_file);
   1979 	if (IPACM_SUCCESS == IPACM_read_firewall_xml(firewall_config.firewall_config_file, &firewall_config))
   1980 	{
   1981 		IPACMDBG_H("QCMAP Firewall XML read OK \n");
   1982 		/* find the number of v4/v6 firewall rules */
   1983 		for (i = 0; i < firewall_config.num_extd_firewall_entries; i++)
   1984 		{
   1985 			if (firewall_config.extd_firewall_entries[i].ip_vsn == 4)
   1986 			{
   1987 				rule_v4++;
   1988 			}
   1989 			else
   1990 			{
   1991 				rule_v6++;
   1992 			}
   1993 		}
   1994 		IPACMDBG_H("firewall rule v4:%d v6:%d total:%d\n", rule_v4, rule_v6, firewall_config.num_extd_firewall_entries);
   1995 	}
   1996 	else
   1997 	{
   1998 		IPACMERR("QCMAP Firewall XML read failed, no that file, use default configuration \n");
   1999 	}
   2000 
   2001 	/* construct ipa_ioc_add_flt_rule with N firewall rules */
   2002 	ipa_ioc_add_flt_rule *m_pFilteringTable = NULL;
   2003 	len = sizeof(struct ipa_ioc_add_flt_rule) + 1 * sizeof(struct ipa_flt_rule_add);
   2004 	m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
   2005 	if (!m_pFilteringTable)
   2006 	{
   2007 		IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
   2008 		return IPACM_FAILURE;
   2009 	}
   2010 
   2011 	if(iptype == IPA_IP_v6 &&
   2012 			firewall_config.firewall_enable == true &&
   2013 			check_dft_firewall_rules_attr_mask(&firewall_config))
   2014 	{
   2015 		m_pFilteringTable->commit = 1;
   2016 		m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
   2017 		m_pFilteringTable->global = false;
   2018 		m_pFilteringTable->ip = IPA_IP_v6;
   2019 		m_pFilteringTable->num_rules = (uint8_t)1;
   2020 
   2021 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   2022 		flt_rule_entry.at_rear = true;
   2023 #ifdef FEATURE_IPA_V3
   2024 		flt_rule_entry.at_rear = false;
   2025 		flt_rule_entry.rule.hashable = false;
   2026 #endif
   2027 		flt_rule_entry.flt_rule_hdl = -1;
   2028 		flt_rule_entry.status = -1;
   2029 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
   2030 		memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(struct ipa_rule_attrib));
   2031 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
   2032 		memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2033 		if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   2034 		{
   2035 			IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
   2036 			free(m_pFilteringTable);
   2037 			return IPACM_FAILURE;
   2038 		}
   2039 		else
   2040 		{
   2041 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
   2042 			ipv6_frag_firewall_flt_rule_hdl = m_pFilteringTable->rules[0].flt_rule_hdl;
   2043 			is_ipv6_frag_firewall_flt_rule_installed = true;
   2044 			IPACMDBG_H("Installed IPv6 frag firewall rule, handle %d.\n", ipv6_frag_firewall_flt_rule_hdl);
   2045 		}
   2046 	}
   2047 
   2048 	if (iptype == IPA_IP_v4)
   2049 	{
   2050 		if (rule_v4 == 0)
   2051 		{
   2052 			memset(m_pFilteringTable, 0, len);
   2053 
   2054 			m_pFilteringTable->commit = 1;
   2055 			m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
   2056 			m_pFilteringTable->global = false;
   2057 			m_pFilteringTable->ip = IPA_IP_v4;
   2058 			m_pFilteringTable->num_rules = (uint8_t)1;
   2059 
   2060 			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   2061 
   2062 			if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4))
   2063 			{
   2064 				IPACMERR("m_routing.GetRoutingTable(rt_tbl_lan_v4) Failed.\n");
   2065 				free(m_pFilteringTable);
   2066 				return IPACM_FAILURE;
   2067 			}
   2068 
   2069 			flt_rule_entry.flt_rule_hdl = -1;
   2070 			flt_rule_entry.status = -1;
   2071 
   2072 			/* firewall disable, all traffic are allowed */
   2073 			if(firewall_config.firewall_enable == true)
   2074 			{
   2075 				flt_rule_entry.at_rear = true;
   2076 
   2077 				/* default action for v4 is go DST_NAT unless user set to exception*/
   2078 				if(firewall_config.rule_action_accept == true)
   2079 				{
   2080 					flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
   2081 				}
   2082 				else
   2083 				{
   2084 					if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
   2085 					{
   2086 						flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
   2087 					}
   2088 					else
   2089 					{
   2090 						flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   2091 					}
   2092 				}
   2093 			}
   2094 			else
   2095 			{
   2096 				flt_rule_entry.at_rear = true;
   2097 				if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
   2098 				{
   2099 					flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
   2100 				}
   2101 				else
   2102 				{
   2103 					flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   2104 				}
   2105             }
   2106 #ifdef FEATURE_IPA_V3
   2107 			flt_rule_entry.at_rear = true;
   2108 			flt_rule_entry.rule.hashable = true;
   2109 #endif
   2110 			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
   2111 			memcpy(&flt_rule_entry.rule.attrib,
   2112 						 &rx_prop->rx[0].attrib,
   2113 						 sizeof(struct ipa_rule_attrib));
   2114 			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   2115 			flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000;
   2116 			flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000;
   2117 
   2118 			memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2119 
   2120 			if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   2121 			{
   2122 				IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
   2123 				free(m_pFilteringTable);
   2124 				return IPACM_FAILURE;
   2125 			}
   2126 			else
   2127 			{
   2128 				IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
   2129 				IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
   2130 			}
   2131 
   2132 			/* copy filter hdls */
   2133 			dft_wan_fl_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl;
   2134 		}
   2135 		else
   2136 		{
   2137 			memset(m_pFilteringTable, 0, len);
   2138 
   2139 			m_pFilteringTable->commit = 1;
   2140 			m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
   2141 			m_pFilteringTable->global = false;
   2142 			m_pFilteringTable->ip = IPA_IP_v4;
   2143 			m_pFilteringTable->num_rules = (uint8_t)1;
   2144 
   2145 			IPACMDBG_H("Retreiving Routing handle for routing table name:%s\n",
   2146 							 IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name);
   2147 			if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4))
   2148 			{
   2149 				IPACMERR("m_routing.GetRoutingTable(&rt_tbl_lan_v4=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_lan_v4);
   2150 				free(m_pFilteringTable);
   2151 				return IPACM_FAILURE;
   2152 			}
   2153 			IPACMDBG_H("Routing handle for wan routing table:0x%x\n", IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl);
   2154 
   2155             if(firewall_config.firewall_enable == true)
   2156             {
   2157 			rule_v4 = 0;
   2158 			for (i = 0; i < firewall_config.num_extd_firewall_entries; i++)
   2159 			{
   2160 				if (firewall_config.extd_firewall_entries[i].ip_vsn == 4)
   2161 				{
   2162 					memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   2163 
   2164 		    			flt_rule_entry.at_rear = true;
   2165 					flt_rule_entry.flt_rule_hdl = -1;
   2166 					flt_rule_entry.status = -1;
   2167 					flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
   2168 
   2169 					/* Accept v4 matched rules*/
   2170                     if(firewall_config.rule_action_accept == true)
   2171 			        {
   2172 						if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
   2173 						{
   2174 							flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
   2175 						}
   2176 						else
   2177 						{
   2178 							flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   2179 						}
   2180 			        }
   2181 			        else
   2182 			        {
   2183 			            flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
   2184                     }
   2185 #ifdef FEATURE_IPA_V3
   2186 					flt_rule_entry.rule.hashable = true;
   2187 #endif
   2188 					memcpy(&flt_rule_entry.rule.attrib,
   2189 								 &firewall_config.extd_firewall_entries[i].attrib,
   2190 								 sizeof(struct ipa_rule_attrib));
   2191 
   2192 					IPACMDBG_H("rx property attrib mask: 0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
   2193 					flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask;
   2194 					flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask;
   2195 					flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data;
   2196 
   2197 					/* check if the rule is define as TCP_UDP, split into 2 rules, 1 for TCP and 1 UDP */
   2198 					if (firewall_config.extd_firewall_entries[i].attrib.u.v4.protocol
   2199 							== IPACM_FIREWALL_IPPROTO_TCP_UDP)
   2200 					{
   2201 						/* insert TCP rule*/
   2202 						flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_TCP;
   2203 						memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2204 
   2205 						IPACMDBG_H("Filter rule attrib mask: 0x%x\n",
   2206 										 m_pFilteringTable->rules[0].rule.attrib.attrib_mask);
   2207 						if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   2208 						{
   2209 							IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
   2210 							free(m_pFilteringTable);
   2211 							return IPACM_FAILURE;
   2212 						}
   2213 						else
   2214 						{
   2215 							IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
   2216 							/* save v4 firewall filter rule handler */
   2217 							IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n",
   2218 											 m_pFilteringTable->rules[rule_v4].flt_rule_hdl,
   2219 											 m_pFilteringTable->rules[rule_v4].status);
   2220 							firewall_hdl_v4[rule_v4] = m_pFilteringTable->rules[0].flt_rule_hdl;
   2221 							num_firewall_v4++;
   2222 							rule_v4++;
   2223 						}
   2224 
   2225 						/* insert UDP rule*/
   2226 						flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_UDP;
   2227 						memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2228 
   2229 						IPACMDBG_H("Filter rule attrib mask: 0x%x\n",
   2230 										 m_pFilteringTable->rules[0].rule.attrib.attrib_mask);
   2231 						if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   2232 						{
   2233 							IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
   2234 							free(m_pFilteringTable);
   2235 							return IPACM_FAILURE;
   2236 						}
   2237 						else
   2238 						{
   2239 							IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
   2240 							/* save v4 firewall filter rule handler */
   2241 							IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n",
   2242 											 m_pFilteringTable->rules[rule_v4].flt_rule_hdl,
   2243 											 m_pFilteringTable->rules[rule_v4].status);
   2244 							firewall_hdl_v4[rule_v4] = m_pFilteringTable->rules[0].flt_rule_hdl;
   2245 							num_firewall_v4++;
   2246 							rule_v4++;
   2247 						}
   2248 					}
   2249 					else
   2250 					{
   2251 						memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2252 
   2253 						IPACMDBG_H("Filter rule attrib mask: 0x%x\n",
   2254 										 m_pFilteringTable->rules[0].rule.attrib.attrib_mask);
   2255 						if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   2256 						{
   2257 							IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
   2258 							free(m_pFilteringTable);
   2259 							return IPACM_FAILURE;
   2260 						}
   2261 						else
   2262 						{
   2263 							IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
   2264 							/* save v4 firewall filter rule handler */
   2265 							IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n",
   2266 											 m_pFilteringTable->rules[rule_v4].flt_rule_hdl,
   2267 											 m_pFilteringTable->rules[rule_v4].status);
   2268 							firewall_hdl_v4[rule_v4] = m_pFilteringTable->rules[0].flt_rule_hdl;
   2269 							num_firewall_v4++;
   2270 							rule_v4++;
   2271 						}
   2272 					}
   2273 				}
   2274 			} /* end of firewall ipv4 filter rule add for loop*/
   2275             }
   2276 			/* configure default filter rule */
   2277 			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   2278 
   2279 			flt_rule_entry.flt_rule_hdl = -1;
   2280 			flt_rule_entry.status = -1;
   2281 
   2282 			/* firewall disable, all traffic are allowed */
   2283             if(firewall_config.firewall_enable == true)
   2284 			{
   2285 			     flt_rule_entry.at_rear = true;
   2286 
   2287 			     /* default action for v4 is go DST_NAT unless user set to exception*/
   2288                              if(firewall_config.rule_action_accept == true)
   2289 			     {
   2290 			        flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
   2291 			     }
   2292 			     else
   2293 			     {
   2294 					if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
   2295 					{
   2296 						flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
   2297 					}
   2298 					else
   2299 					{
   2300 						flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   2301 					}
   2302 				}
   2303 		    }
   2304 			else
   2305 			{
   2306 			    flt_rule_entry.at_rear = true;
   2307 				if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
   2308 				{
   2309 					flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
   2310 				}
   2311 				else
   2312 				{
   2313 					flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   2314 				}
   2315             }
   2316 #ifdef FEATURE_IPA_V3
   2317 			flt_rule_entry.rule.hashable = true;
   2318 #endif
   2319 			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
   2320 			memcpy(&flt_rule_entry.rule.attrib,
   2321 						 &rx_prop->rx[0].attrib,
   2322 						 sizeof(struct ipa_rule_attrib));
   2323 			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   2324 			flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000;
   2325 			flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000;
   2326 
   2327 			memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2328 
   2329 			IPACMDBG_H("Filter rule attrib mask: 0x%x\n",
   2330 							 m_pFilteringTable->rules[0].rule.attrib.attrib_mask);
   2331 			if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   2332 			{
   2333 				IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
   2334 				free(m_pFilteringTable);
   2335 				return IPACM_FAILURE;
   2336 			}
   2337 			else
   2338 			{
   2339 				IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
   2340 				IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
   2341 			}
   2342 
   2343 			/* copy filter hdls */
   2344 			dft_wan_fl_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl;
   2345 		}
   2346 
   2347 	}
   2348 	else
   2349 	{
   2350 		if (rule_v6 == 0)
   2351 		{
   2352 			memset(m_pFilteringTable, 0, len);
   2353 
   2354 			m_pFilteringTable->commit = 1;
   2355 			m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
   2356 			m_pFilteringTable->global = false;
   2357 			m_pFilteringTable->ip = IPA_IP_v6;
   2358 			m_pFilteringTable->num_rules = (uint8_t)1;
   2359 
   2360 			/* Construct ICMP rule */
   2361 			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   2362 			flt_rule_entry.at_rear = true;
   2363 			flt_rule_entry.flt_rule_hdl = -1;
   2364 			flt_rule_entry.status = -1;
   2365 			flt_rule_entry.rule.retain_hdr = 1;
   2366 			flt_rule_entry.rule.eq_attrib_type = 0;
   2367 			flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
   2368 #ifdef FEATURE_IPA_V3
   2369 			flt_rule_entry.rule.hashable = true;
   2370 #endif
   2371 			memcpy(&flt_rule_entry.rule.attrib,
   2372 					 &rx_prop->rx[0].attrib,
   2373 					 sizeof(struct ipa_rule_attrib));
   2374 			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
   2375 			flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6;
   2376 			memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2377 
   2378 			if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   2379 			{
   2380 				IPACMERR("Error Adding Filtering rules, aborting...\n");
   2381 				free(m_pFilteringTable);
   2382 				return IPACM_FAILURE;
   2383 			}
   2384 			else
   2385 			{
   2386 				IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
   2387 				IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
   2388 			}
   2389 			/* copy filter hdls */
   2390 			dft_wan_fl_hdl[2] = m_pFilteringTable->rules[0].flt_rule_hdl;
   2391 
   2392 			/* End of construct ICMP rule */
   2393 
   2394 			/* v6 default route */
   2395 			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   2396 			if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v6)) //rt_tbl_wan_v6 rt_tbl_v6
   2397 			{
   2398 				IPACMERR("m_routing.GetRoutingTable(rt_tbl_wan_v6) Failed.\n");
   2399 				free(m_pFilteringTable);
   2400 				return IPACM_FAILURE;
   2401 			}
   2402 
   2403 			flt_rule_entry.flt_rule_hdl = -1;
   2404 			flt_rule_entry.status = -1;
   2405 			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl;
   2406 
   2407 			/* firewall disable, all traffic are allowed */
   2408                         if(firewall_config.firewall_enable == true)
   2409 			{
   2410 			   flt_rule_entry.at_rear = true;
   2411 
   2412 			   /* default action for v6 is PASS_TO_ROUTE unless user set to exception*/
   2413                            if(firewall_config.rule_action_accept == true)
   2414 			   {
   2415 			       flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
   2416 			   }
   2417 			   else
   2418 			   {
   2419 			       flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   2420                            }
   2421 		        }
   2422 			else
   2423 			{
   2424 			  flt_rule_entry.at_rear = true;
   2425 			  flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   2426                         }
   2427 #ifdef FEATURE_IPA_V3
   2428 			flt_rule_entry.rule.hashable = true;
   2429 #endif
   2430 			memcpy(&flt_rule_entry.rule.attrib,
   2431 						 &rx_prop->rx[0].attrib,
   2432 						 sizeof(struct ipa_rule_attrib));
   2433 			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   2434 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;
   2435 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
   2436 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
   2437 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
   2438 			flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000;
   2439 			flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
   2440 			flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
   2441 			flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
   2442 
   2443 			memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2444 
   2445 			if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   2446 			{
   2447 				IPACMERR("Error Adding Filtering rules, aborting...\n");
   2448 				free(m_pFilteringTable);
   2449 				return IPACM_FAILURE;
   2450 			}
   2451 			else
   2452 			{
   2453 				IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
   2454 				IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
   2455 			}
   2456 
   2457 			/* copy filter hdls */
   2458 			dft_wan_fl_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl;
   2459 		}
   2460 		else
   2461 		{
   2462 			memset(m_pFilteringTable, 0, len);
   2463 
   2464 			m_pFilteringTable->commit = 1;
   2465 			m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
   2466 			m_pFilteringTable->global = false;
   2467 			m_pFilteringTable->ip = IPA_IP_v6;
   2468 			m_pFilteringTable->num_rules = (uint8_t)1;
   2469 
   2470 			if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v6))
   2471 			{
   2472 				IPACMERR("m_routing.GetRoutingTable(rt_tbl_wan_v6) Failed.\n");
   2473 				free(m_pFilteringTable);
   2474 				return IPACM_FAILURE;
   2475 			}
   2476 
   2477             if(firewall_config.firewall_enable == true)
   2478             {
   2479 			rule_v6 = 0;
   2480 			for (i = 0; i < firewall_config.num_extd_firewall_entries; i++)
   2481 			{
   2482 				if (firewall_config.extd_firewall_entries[i].ip_vsn == 6)
   2483 				{
   2484 					memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   2485 
   2486 		    			flt_rule_entry.at_rear = true;
   2487 					flt_rule_entry.flt_rule_hdl = -1;
   2488 					flt_rule_entry.status = -1;
   2489 
   2490 				    /* matched rules for v6 go PASS_TO_ROUTE */
   2491                                     if(firewall_config.rule_action_accept == true)
   2492 			            {
   2493 			                flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   2494 			            }
   2495 			            else
   2496 			            {
   2497 					flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
   2498                                     }
   2499 #ifdef FEATURE_IPA_V3
   2500 					flt_rule_entry.rule.hashable = true;
   2501 #endif
   2502 		    			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl;
   2503 					memcpy(&flt_rule_entry.rule.attrib,
   2504 								 &firewall_config.extd_firewall_entries[i].attrib,
   2505 								 sizeof(struct ipa_rule_attrib));
   2506 					flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask;
   2507 					flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask;
   2508 					flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data;
   2509 
   2510 					/* check if the rule is define as TCP/UDP */
   2511 					if (firewall_config.extd_firewall_entries[i].attrib.u.v6.next_hdr == IPACM_FIREWALL_IPPROTO_TCP_UDP)
   2512 					{
   2513 						/* insert TCP rule*/
   2514 						flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP;
   2515 						memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2516 						if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   2517 						{
   2518 							IPACMERR("Error Adding Filtering rules, aborting...\n");
   2519 							free(m_pFilteringTable);
   2520 							return IPACM_FAILURE;
   2521 						}
   2522 						else
   2523 						{
   2524 							IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
   2525 							/* save v4 firewall filter rule handler */
   2526 							IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
   2527 							firewall_hdl_v6[rule_v6] = m_pFilteringTable->rules[0].flt_rule_hdl;
   2528 							num_firewall_v6++;
   2529 							rule_v6++;
   2530 						}
   2531 
   2532 						/* insert UDP rule*/
   2533 						flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_UDP;
   2534 						memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2535 						if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   2536 						{
   2537 							IPACMERR("Error Adding Filtering rules, aborting...\n");
   2538 							free(m_pFilteringTable);
   2539 							return IPACM_FAILURE;
   2540 						}
   2541 						else
   2542 						{
   2543 							IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
   2544 							/* save v6 firewall filter rule handler */
   2545 							IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
   2546 							firewall_hdl_v6[rule_v6] = m_pFilteringTable->rules[0].flt_rule_hdl;
   2547 							num_firewall_v6++;
   2548 							rule_v6++;
   2549 						}
   2550 					}
   2551 					else
   2552 					{
   2553 						memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2554 						if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   2555 						{
   2556 							IPACMERR("Error Adding Filtering rules, aborting...\n");
   2557 							free(m_pFilteringTable);
   2558 							return IPACM_FAILURE;
   2559 						}
   2560 						else
   2561 						{
   2562 							IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
   2563 							/* save v6 firewall filter rule handler */
   2564 							IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
   2565 							firewall_hdl_v6[rule_v6] = m_pFilteringTable->rules[0].flt_rule_hdl;
   2566 							num_firewall_v6++;
   2567 							rule_v6++;
   2568 						}
   2569 					}
   2570 				}
   2571 			} /* end of firewall ipv6 filter rule add for loop*/
   2572             }
   2573 
   2574 			/* Construct ICMP rule */
   2575 			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   2576 			flt_rule_entry.at_rear = true;
   2577 			flt_rule_entry.flt_rule_hdl = -1;
   2578 			flt_rule_entry.status = -1;
   2579 			flt_rule_entry.rule.retain_hdr = 1;
   2580 			flt_rule_entry.rule.eq_attrib_type = 0;
   2581 			flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
   2582 #ifdef FEATURE_IPA_V3
   2583 			flt_rule_entry.rule.hashable = true;
   2584 #endif
   2585 			memcpy(&flt_rule_entry.rule.attrib,
   2586 					 &rx_prop->rx[0].attrib,
   2587 					 sizeof(struct ipa_rule_attrib));
   2588 			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
   2589 			flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6;
   2590 			memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2591 
   2592 			if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   2593 			{
   2594 				IPACMERR("Error Adding Filtering rules, aborting...\n");
   2595 				free(m_pFilteringTable);
   2596 				return IPACM_FAILURE;
   2597 			}
   2598 			else
   2599 			{
   2600 				IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
   2601 				IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
   2602 			}
   2603 			/* copy filter hdls */
   2604 			dft_wan_fl_hdl[2] = m_pFilteringTable->rules[0].flt_rule_hdl;
   2605 			/* End of construct ICMP rule */
   2606 
   2607 			/* setup default wan filter rule */
   2608 			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   2609 
   2610 			flt_rule_entry.flt_rule_hdl = -1;
   2611 			flt_rule_entry.status = -1;
   2612 			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl;
   2613 
   2614 			/* firewall disable, all traffic are allowed */
   2615                         if(firewall_config.firewall_enable == true)
   2616 			{
   2617 			   flt_rule_entry.at_rear = true;
   2618 
   2619 			   /* default action for v6 is PASS_TO_ROUTE unless user set to exception*/
   2620                if(firewall_config.rule_action_accept == true)
   2621 			   {
   2622 			        flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
   2623 			   }
   2624 			   else
   2625 			   {
   2626 			flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   2627                            }
   2628 		        }
   2629 			else
   2630 			{
   2631 			  flt_rule_entry.at_rear = true;
   2632 			  flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   2633                         }
   2634 #ifdef FEATURE_IPA_V3
   2635 			flt_rule_entry.rule.hashable = true;
   2636 #endif
   2637 			memcpy(&flt_rule_entry.rule.attrib,
   2638 						 &rx_prop->rx[0].attrib,
   2639 						 sizeof(struct ipa_rule_attrib));
   2640 			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   2641 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;
   2642 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
   2643 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
   2644 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
   2645 			flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000;
   2646 			flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
   2647 			flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
   2648 			flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
   2649 
   2650 			memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2651 
   2652 			if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   2653 			{
   2654 				IPACMERR("Error Adding Filtering rules, aborting...\n");
   2655 				free(m_pFilteringTable);
   2656 				return IPACM_FAILURE;
   2657 			}
   2658 			else
   2659 			{
   2660 				IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
   2661 				IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
   2662 			}
   2663 			/* copy filter hdls*/
   2664 			dft_wan_fl_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl;
   2665 		}
   2666 	}
   2667 
   2668 	if(m_pFilteringTable != NULL)
   2669 	{
   2670 		free(m_pFilteringTable);
   2671 	}
   2672 	return IPACM_SUCCESS;
   2673 }
   2674 
   2675 /* configure the initial firewall filter rules */
   2676 int IPACM_Wan::config_dft_firewall_rules_ex(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype)
   2677 {
   2678 	struct ipa_flt_rule_add flt_rule_entry;
   2679 	int i;
   2680 	int num_rules = 0, original_num_rules = 0;
   2681 	ipa_ioc_get_rt_tbl_indx rt_tbl_idx;
   2682 	ipa_ioc_generate_flt_eq flt_eq;
   2683 	int pos = rule_offset;
   2684 
   2685 	IPACMDBG_H("ip-family: %d; \n", iptype);
   2686 
   2687 	if (rx_prop == NULL)
   2688 	{
   2689 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
   2690 		return IPACM_SUCCESS;
   2691 	}
   2692 
   2693 	if(rules == NULL || rule_offset < 0)
   2694 	{
   2695 		IPACMERR("No filtering table is available.\n");
   2696 		return IPACM_FAILURE;
   2697 	}
   2698 
   2699 	/* default firewall is disable and the rule action is drop */
   2700 	memset(&firewall_config, 0, sizeof(firewall_config));
   2701 	strlcpy(firewall_config.firewall_config_file, "/etc/mobileap_firewall.xml", sizeof(firewall_config.firewall_config_file));
   2702 
   2703 	IPACMDBG_H("Firewall XML file is %s \n", firewall_config.firewall_config_file);
   2704 	if (IPACM_SUCCESS == IPACM_read_firewall_xml(firewall_config.firewall_config_file, &firewall_config))
   2705 	{
   2706 		IPACMDBG_H("QCMAP Firewall XML read OK \n");
   2707 	}
   2708 	else
   2709 	{
   2710 		IPACMERR("QCMAP Firewall XML read failed, no that file, use default configuration \n");
   2711 	}
   2712 
   2713 	/* add IPv6 frag rule when firewall is enabled*/
   2714 	if(iptype == IPA_IP_v6 &&
   2715 			firewall_config.firewall_enable == true &&
   2716 			check_dft_firewall_rules_attr_mask(&firewall_config))
   2717 	{
   2718 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   2719 		flt_rule_entry.at_rear = true;
   2720 #ifdef FEATURE_IPA_V3
   2721 		flt_rule_entry.at_rear = false;
   2722 #endif
   2723 		flt_rule_entry.flt_rule_hdl = -1;
   2724 		flt_rule_entry.status = -1;
   2725 
   2726 		flt_rule_entry.rule.retain_hdr = 1;
   2727 		flt_rule_entry.rule.to_uc = 0;
   2728 		flt_rule_entry.rule.eq_attrib_type = 1;
   2729 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   2730 #ifdef FEATURE_IPA_V3
   2731 		flt_rule_entry.at_rear = false;
   2732 		flt_rule_entry.rule.hashable = false;
   2733 #endif
   2734 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
   2735 		rt_tbl_idx.ip = IPA_IP_v6;
   2736 		strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
   2737 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   2738 		if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
   2739 		{
   2740 			IPACMERR("Failed to get routing table index from name\n");
   2741 			return IPACM_FAILURE;
   2742 		}
   2743 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
   2744 		IPACMDBG_H("IPv6 frag flt rule uses routing table index %d\n", rt_tbl_idx.idx);
   2745 
   2746 		flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask;
   2747 		flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask;
   2748 		flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data;
   2749 
   2750 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
   2751 
   2752 		change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
   2753 
   2754 		memset(&flt_eq, 0, sizeof(flt_eq));
   2755 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   2756 		flt_eq.ip = IPA_IP_v6;
   2757 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   2758 		{
   2759 			IPACMERR("Failed to get eq_attrib\n");
   2760 			return IPACM_FAILURE;
   2761 		}
   2762 		memcpy(&flt_rule_entry.rule.eq_attrib,
   2763 			&flt_eq.eq_attrib,
   2764 			sizeof(flt_rule_entry.rule.eq_attrib));
   2765 
   2766 		memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2767 		pos++;
   2768 		IPACM_Wan::num_v6_flt_rule++;
   2769 	}
   2770 
   2771 	if (iptype == IPA_IP_v4)
   2772 	{
   2773 		original_num_rules = IPACM_Wan::num_v4_flt_rule;
   2774 		if(firewall_config.firewall_enable == true)
   2775 		{
   2776 			for (i = 0; i < firewall_config.num_extd_firewall_entries; i++)
   2777 			{
   2778 				if (firewall_config.extd_firewall_entries[i].ip_vsn == 4)
   2779 				{
   2780 					memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   2781 
   2782 					flt_rule_entry.at_rear = true;
   2783 					flt_rule_entry.flt_rule_hdl = -1;
   2784 					flt_rule_entry.status = -1;
   2785 
   2786 					flt_rule_entry.rule.retain_hdr = 1;
   2787 					flt_rule_entry.rule.to_uc = 0;
   2788 					flt_rule_entry.rule.eq_attrib_type = 1;
   2789 
   2790 					/* Accept v4 matched rules*/
   2791 					if(firewall_config.rule_action_accept == true)
   2792 					{
   2793 						flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
   2794 					}
   2795 					else
   2796 					{
   2797 						flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   2798 					}
   2799 #ifdef FEATURE_IPA_V3
   2800 					flt_rule_entry.rule.hashable = true;
   2801 #endif
   2802 					memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
   2803 					rt_tbl_idx.ip = iptype;
   2804 					if(flt_rule_entry.rule.action == IPA_PASS_TO_ROUTING)
   2805 					{
   2806 						strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
   2807 					}
   2808 					else /*pass to dst nat*/
   2809 					{
   2810 						strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, IPA_RESOURCE_NAME_MAX);
   2811 					}
   2812 					rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   2813 					if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
   2814 					{
   2815 						IPACMERR("Failed to get routing table index from name\n");
   2816 						return IPACM_FAILURE;
   2817 					}
   2818 					flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
   2819 
   2820 					IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
   2821 
   2822 					memcpy(&flt_rule_entry.rule.attrib,
   2823 						&firewall_config.extd_firewall_entries[i].attrib,
   2824 						sizeof(struct ipa_rule_attrib));
   2825 
   2826 					flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask;
   2827 					flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask;
   2828 					flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data;
   2829 
   2830 					change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib);
   2831 
   2832 					/* check if the rule is define as TCP_UDP, split into 2 rules, 1 for TCP and 1 UDP */
   2833 					if (firewall_config.extd_firewall_entries[i].attrib.u.v4.protocol == IPACM_FIREWALL_IPPROTO_TCP_UDP)
   2834 					{
   2835 						/* insert TCP rule*/
   2836 						flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_TCP;
   2837 
   2838 						memset(&flt_eq, 0, sizeof(flt_eq));
   2839 						memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   2840 						flt_eq.ip = iptype;
   2841 						if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   2842 						{
   2843 							IPACMERR("Failed to get eq_attrib\n");
   2844 							return IPACM_FAILURE;
   2845 						}
   2846 						memcpy(&flt_rule_entry.rule.eq_attrib,
   2847 							&flt_eq.eq_attrib,
   2848 							sizeof(flt_rule_entry.rule.eq_attrib));
   2849 
   2850 						memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2851 						IPACMDBG_H("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask);
   2852 						pos++;
   2853 						num_firewall_v4++;
   2854 						IPACM_Wan::num_v4_flt_rule++;
   2855 
   2856 						/* insert UDP rule*/
   2857 						flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_UDP;
   2858 
   2859 						memset(&flt_eq, 0, sizeof(flt_eq));
   2860 						memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   2861 						flt_eq.ip = iptype;
   2862 						if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   2863 						{
   2864 							IPACMERR("Failed to get eq_attrib\n");
   2865 							return IPACM_FAILURE;
   2866 						}
   2867 						memcpy(&flt_rule_entry.rule.eq_attrib,
   2868 							&flt_eq.eq_attrib,
   2869 							sizeof(flt_rule_entry.rule.eq_attrib));
   2870 
   2871 						memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2872 						IPACMDBG_H("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask);
   2873 						pos++;
   2874 						num_firewall_v4++;
   2875 						IPACM_Wan::num_v4_flt_rule++;
   2876 					}
   2877 					else
   2878 					{
   2879 						memset(&flt_eq, 0, sizeof(flt_eq));
   2880 						memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   2881 						flt_eq.ip = iptype;
   2882 						if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   2883 						{
   2884 							IPACMERR("Failed to get eq_attrib\n");
   2885 							return IPACM_FAILURE;
   2886 						}
   2887 						memcpy(&flt_rule_entry.rule.eq_attrib,
   2888 							&flt_eq.eq_attrib,
   2889 							sizeof(flt_rule_entry.rule.eq_attrib));
   2890 
   2891 						memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2892 						IPACMDBG_H("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask);
   2893 						pos++;
   2894 						num_firewall_v4++;
   2895 						IPACM_Wan::num_v4_flt_rule++;
   2896 					}
   2897 				}
   2898 			} /* end of firewall ipv4 filter rule add for loop*/
   2899 		}
   2900 		/* configure default filter rule */
   2901 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   2902 
   2903 		flt_rule_entry.at_rear = true;
   2904 		flt_rule_entry.flt_rule_hdl = -1;
   2905 		flt_rule_entry.status = -1;
   2906 
   2907 		flt_rule_entry.rule.retain_hdr = 1;
   2908 		flt_rule_entry.rule.to_uc = 0;
   2909 		flt_rule_entry.rule.eq_attrib_type = 1;
   2910 
   2911 		/* firewall disable, all traffic are allowed */
   2912 		if(firewall_config.firewall_enable == true)
   2913 		{
   2914 			/* default action for v4 is go DST_NAT unless user set to exception*/
   2915 			if(firewall_config.rule_action_accept == true)
   2916 			{
   2917 				flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   2918 			}
   2919 			else
   2920 			{
   2921 				flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
   2922 			}
   2923 		}
   2924 		else
   2925 		{
   2926 			if(isWan_Bridge_Mode())
   2927 			{
   2928 				IPACMDBG_H("ODU is in bridge mode. \n");
   2929 				flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   2930 			}
   2931 			else
   2932 			{
   2933 				flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
   2934 			}
   2935 		}
   2936 #ifdef FEATURE_IPA_V3
   2937 		flt_rule_entry.rule.hashable = true;
   2938 #endif
   2939 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
   2940 		rt_tbl_idx.ip = iptype;
   2941 
   2942 		if(flt_rule_entry.rule.action == IPA_PASS_TO_ROUTING)
   2943 		{
   2944 			strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
   2945 		}
   2946 		else /*pass to dst nat*/
   2947 		{
   2948 			strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, IPA_RESOURCE_NAME_MAX);
   2949 		}
   2950 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   2951 
   2952 		if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
   2953 		{
   2954 			IPACMERR("Failed to get routing table index from name\n");
   2955 			return IPACM_FAILURE;
   2956 		}
   2957 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
   2958 
   2959 		IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
   2960 
   2961 		memcpy(&flt_rule_entry.rule.attrib,
   2962 			&rx_prop->rx[0].attrib,
   2963 			sizeof(struct ipa_rule_attrib));
   2964 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   2965 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000;
   2966 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000;
   2967 
   2968 		change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib);
   2969 
   2970 		memset(&flt_eq, 0, sizeof(flt_eq));
   2971 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   2972 		flt_eq.ip = iptype;
   2973 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   2974 		{
   2975 			IPACMERR("Failed to get eq_attrib\n");
   2976 			return IPACM_FAILURE;
   2977 		}
   2978 
   2979 		memcpy(&flt_rule_entry.rule.eq_attrib,
   2980 			&flt_eq.eq_attrib,
   2981 			sizeof(flt_rule_entry.rule.eq_attrib));
   2982 
   2983 		memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   2984 		IPACMDBG_H("Filter rule attrib mask: 0x%x\n",	rules[pos].rule.attrib.attrib_mask);
   2985 		pos++;
   2986 		num_firewall_v4++;
   2987 		IPACM_Wan::num_v4_flt_rule++;
   2988 
   2989 		num_rules = IPACM_Wan::num_v4_flt_rule - original_num_rules - 1;
   2990 	}
   2991 	else
   2992 	{
   2993 		original_num_rules = IPACM_Wan::num_v6_flt_rule;
   2994 
   2995 		if(firewall_config.firewall_enable == true)
   2996 		{
   2997 			for (i = 0; i < firewall_config.num_extd_firewall_entries; i++)
   2998 			{
   2999 				if (firewall_config.extd_firewall_entries[i].ip_vsn == 6)
   3000 				{
   3001 					memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   3002 
   3003 					flt_rule_entry.at_rear = true;
   3004 					flt_rule_entry.flt_rule_hdl = -1;
   3005 					flt_rule_entry.status = -1;
   3006 
   3007 					flt_rule_entry.rule.retain_hdr = 1;
   3008 					flt_rule_entry.rule.to_uc = 0;
   3009 					flt_rule_entry.rule.eq_attrib_type = 1;
   3010 					flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   3011 #ifdef FEATURE_IPA_V3
   3012 					flt_rule_entry.rule.hashable = true;
   3013 #endif
   3014 					memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
   3015 					rt_tbl_idx.ip = iptype;
   3016 
   3017 					/* matched rules for v6 go PASS_TO_ROUTE */
   3018 					if(firewall_config.rule_action_accept == true)
   3019 					{
   3020 						strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX);
   3021 					}
   3022 					else
   3023 					{
   3024 						strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
   3025 					}
   3026 					rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   3027 
   3028 					if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
   3029 					{
   3030 						IPACMERR("Failed to get routing table index from name\n");
   3031 						return IPACM_FAILURE;
   3032 					}
   3033 					flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
   3034 
   3035 					IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
   3036 
   3037 					memcpy(&flt_rule_entry.rule.attrib,
   3038 						&firewall_config.extd_firewall_entries[i].attrib,
   3039 						sizeof(struct ipa_rule_attrib));
   3040 
   3041 					flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask;
   3042 					flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask;
   3043 					flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data;
   3044 
   3045 					change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
   3046 
   3047 					/* check if the rule is define as TCP/UDP */
   3048 					if (firewall_config.extd_firewall_entries[i].attrib.u.v6.next_hdr == IPACM_FIREWALL_IPPROTO_TCP_UDP)
   3049 					{
   3050 						/* insert TCP rule*/
   3051 						flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP;
   3052 
   3053 						memset(&flt_eq, 0, sizeof(flt_eq));
   3054 						memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   3055 						flt_eq.ip = iptype;
   3056 						if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   3057 						{
   3058 							IPACMERR("Failed to get eq_attrib\n");
   3059 							return IPACM_FAILURE;
   3060 						}
   3061 
   3062 						memcpy(&flt_rule_entry.rule.eq_attrib,
   3063 							&flt_eq.eq_attrib,
   3064 							sizeof(flt_rule_entry.rule.eq_attrib));
   3065 						memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3066 						pos++;
   3067 						num_firewall_v6++;
   3068 						IPACM_Wan::num_v6_flt_rule++;
   3069 
   3070 						/* insert UDP rule*/
   3071 						flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_UDP;
   3072 
   3073 						memset(&flt_eq, 0, sizeof(flt_eq));
   3074 						memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   3075 						flt_eq.ip = iptype;
   3076 						if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   3077 						{
   3078 							IPACMERR("Failed to get eq_attrib\n");
   3079 							return IPACM_FAILURE;
   3080 						}
   3081 
   3082 						memcpy(&flt_rule_entry.rule.eq_attrib,
   3083 							&flt_eq.eq_attrib,
   3084 							sizeof(flt_rule_entry.rule.eq_attrib));
   3085 						memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3086 						pos++;
   3087 						num_firewall_v6++;
   3088 						IPACM_Wan::num_v6_flt_rule++;
   3089 					}
   3090 					else
   3091 					{
   3092 						memset(&flt_eq, 0, sizeof(flt_eq));
   3093 						memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   3094 						flt_eq.ip = iptype;
   3095 						if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   3096 						{
   3097 							IPACMERR("Failed to get eq_attrib\n");
   3098 							return IPACM_FAILURE;
   3099 						}
   3100 
   3101 						memcpy(&flt_rule_entry.rule.eq_attrib,
   3102 							&flt_eq.eq_attrib,
   3103 							sizeof(flt_rule_entry.rule.eq_attrib));
   3104 						memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3105 						pos++;
   3106 						num_firewall_v6++;
   3107 						IPACM_Wan::num_v6_flt_rule++;
   3108 					}
   3109 				}
   3110 			} /* end of firewall ipv6 filter rule add for loop*/
   3111 		}
   3112 
   3113 		/* setup default wan filter rule */
   3114 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   3115 
   3116 		flt_rule_entry.at_rear = true;
   3117 		flt_rule_entry.flt_rule_hdl = -1;
   3118 		flt_rule_entry.status = -1;
   3119 
   3120 		flt_rule_entry.rule.retain_hdr = 1;
   3121 		flt_rule_entry.rule.to_uc = 0;
   3122 		flt_rule_entry.rule.eq_attrib_type = 1;
   3123 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   3124 #ifdef FEATURE_IPA_V3
   3125 		flt_rule_entry.rule.hashable = true;
   3126 #endif
   3127 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
   3128 		rt_tbl_idx.ip = iptype;
   3129 		/* firewall disable, all traffic are allowed */
   3130 		if(firewall_config.firewall_enable == true)
   3131 		{
   3132 			/* default action for v6 is PASS_TO_ROUTE unless user set to exception*/
   3133 			if(firewall_config.rule_action_accept == true)
   3134 			{
   3135 				strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
   3136 			}
   3137 			else
   3138 			{
   3139 				strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX);
   3140 			}
   3141 		}
   3142 		else
   3143 		{
   3144 			strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX);
   3145 		}
   3146 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   3147 		if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
   3148 		{
   3149 			IPACMERR("Failed to get routing table index from name\n");
   3150 			return IPACM_FAILURE;
   3151 		}
   3152 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
   3153 
   3154 		IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
   3155 
   3156 		memcpy(&flt_rule_entry.rule.attrib,
   3157 			&rx_prop->rx[1].attrib,
   3158 			sizeof(struct ipa_rule_attrib));
   3159 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   3160 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;
   3161 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
   3162 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
   3163 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
   3164 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000;
   3165 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
   3166 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
   3167 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
   3168 
   3169 		change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
   3170 
   3171 		memset(&flt_eq, 0, sizeof(flt_eq));
   3172 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   3173 		flt_eq.ip = iptype;
   3174 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   3175 		{
   3176 			IPACMERR("Failed to get eq_attrib\n");
   3177 			return IPACM_FAILURE;
   3178 		}
   3179 		memcpy(&flt_rule_entry.rule.eq_attrib,
   3180 			&flt_eq.eq_attrib,
   3181 			sizeof(flt_rule_entry.rule.eq_attrib));
   3182 		memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3183 		pos++;
   3184 		num_firewall_v6++;
   3185 		IPACM_Wan::num_v6_flt_rule++;
   3186 
   3187 		num_rules = IPACM_Wan::num_v6_flt_rule - original_num_rules - 1;
   3188 	}
   3189 	IPACMDBG_H("Constructed %d firewall rules for ip type %d\n", num_rules, iptype);
   3190 	return IPACM_SUCCESS;
   3191 }
   3192 
   3193 int IPACM_Wan::init_fl_rule_ex(ipa_ip_type iptype)
   3194 {
   3195 	int res = IPACM_SUCCESS;
   3196 
   3197 	/* ADD corresponding ipa_rm_resource_name of RX-endpoint before adding all IPV4V6 FT-rules */
   3198 	IPACMDBG_H(" dun add producer dependency from %s with registered rx-prop\n", dev_name);
   3199 
   3200 	if(iptype == IPA_IP_v4)
   3201 	{
   3202 		if(modem_ipv4_pdn_index == 0)	/* install ipv4 default modem DL filtering rules only once */
   3203 		{
   3204 			/* reset the num_v4_flt_rule*/
   3205 			IPACM_Wan::num_v4_flt_rule = 0;
   3206 			add_dft_filtering_rule(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4);
   3207 		}
   3208 	}
   3209 	else if(iptype == IPA_IP_v6)
   3210 	{
   3211 		if(modem_ipv6_pdn_index == 0)	/* install ipv6 default modem DL filtering rules only once */
   3212 		{
   3213 			/* reset the num_v6_flt_rule*/
   3214 			IPACM_Wan::num_v6_flt_rule = 0;
   3215 			add_dft_filtering_rule(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6);
   3216 		}
   3217 	}
   3218 	else
   3219 	{
   3220 		IPACMERR("IP type is not expected.\n");
   3221 		res = IPACM_FAILURE;
   3222 		goto fail;
   3223 	}
   3224 	install_wan_filtering_rule(false);
   3225 
   3226 fail:
   3227 	return res;
   3228 }
   3229 
   3230 int IPACM_Wan::add_icmp_alg_rules(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype)
   3231 {
   3232 	int res = IPACM_SUCCESS, i, original_num_rules = 0, num_rules = 0;
   3233 	struct ipa_flt_rule_add flt_rule_entry;
   3234 	IPACM_Config* ipacm_config = IPACM_Iface::ipacmcfg;
   3235 	ipa_ioc_generate_flt_eq flt_eq;
   3236 	ipa_ioc_get_rt_tbl_indx rt_tbl_idx;
   3237 
   3238 	if(rules == NULL || rule_offset < 0)
   3239 	{
   3240 		IPACMERR("No filtering table is available.\n");
   3241 		return IPACM_FAILURE;
   3242 	}
   3243 
   3244 	if(iptype == IPA_IP_v4)
   3245 	{
   3246 		original_num_rules = IPACM_Wan::num_v4_flt_rule;
   3247 
   3248 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
   3249 		strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
   3250 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   3251 		rt_tbl_idx.ip = iptype;
   3252 		if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
   3253 		{
   3254 			IPACMERR("Failed to get routing table index from name\n");
   3255 			res = IPACM_FAILURE;
   3256 			goto fail;
   3257 		}
   3258 
   3259 		IPACMDBG_H("WAN DL routing table %s has index %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, rt_tbl_idx.idx);
   3260 
   3261 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   3262 
   3263 		flt_rule_entry.at_rear = true;
   3264 		flt_rule_entry.flt_rule_hdl = -1;
   3265 		flt_rule_entry.status = -1;
   3266 
   3267 		flt_rule_entry.rule.retain_hdr = 1;
   3268 		flt_rule_entry.rule.to_uc = 0;
   3269 		flt_rule_entry.rule.eq_attrib_type = 1;
   3270 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   3271 #ifdef FEATURE_IPA_V3
   3272 		flt_rule_entry.rule.hashable = true;
   3273 #endif
   3274 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
   3275 
   3276 		/* Configuring ICMP filtering rule */
   3277 		memcpy(&flt_rule_entry.rule.attrib,
   3278 					 &rx_prop->rx[0].attrib,
   3279 					 sizeof(flt_rule_entry.rule.attrib));
   3280 		/* Multiple PDNs may exist so keep meta-data */
   3281 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
   3282 		flt_rule_entry.rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP;
   3283 
   3284 		memset(&flt_eq, 0, sizeof(flt_eq));
   3285 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   3286 		flt_eq.ip = iptype;
   3287 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   3288 		{
   3289 			IPACMERR("Failed to get eq_attrib\n");
   3290 			res = IPACM_FAILURE;
   3291 			goto fail;
   3292 		}
   3293 
   3294 		memcpy(&flt_rule_entry.rule.eq_attrib,
   3295 					 &flt_eq.eq_attrib,
   3296 					 sizeof(flt_rule_entry.rule.eq_attrib));
   3297 
   3298 		memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3299 
   3300 		IPACM_Wan::num_v4_flt_rule++;
   3301 
   3302 		/* Configure ALG filtering rules */
   3303 		memcpy(&flt_rule_entry.rule.attrib,
   3304 					 &rx_prop->rx[0].attrib,
   3305 					 sizeof(flt_rule_entry.rule.attrib));
   3306 		/* remove meta data mask */
   3307 		flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA);
   3308 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_PORT;
   3309 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
   3310 		for(i = 0; i < ipacm_config->ipa_num_alg_ports; i++)
   3311 		{
   3312 			flt_rule_entry.rule.attrib.src_port = ipacm_config->alg_table[i].port;
   3313 			flt_rule_entry.rule.attrib.u.v4.protocol = ipacm_config->alg_table[i].protocol;
   3314 
   3315 			memset(&flt_eq, 0, sizeof(flt_eq));
   3316 			memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   3317 			flt_eq.ip = iptype;
   3318 			if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   3319 			{
   3320 				IPACMERR("Failed to get eq_attrib\n");
   3321 				res = IPACM_FAILURE;
   3322 				goto fail;
   3323 			}
   3324 			memcpy(&flt_rule_entry.rule.eq_attrib,
   3325 						 &flt_eq.eq_attrib,
   3326 						 sizeof(flt_rule_entry.rule.eq_attrib));
   3327 			memcpy(&(rules[rule_offset + 1 + i]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3328 			IPACM_Wan::num_v4_flt_rule++;
   3329 		}
   3330 
   3331 		memcpy(&flt_rule_entry.rule.attrib,
   3332 					 &rx_prop->rx[0].attrib,
   3333 					 sizeof(flt_rule_entry.rule.attrib));
   3334 		/* remove meta data mask */
   3335 		flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA);
   3336 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_PORT;
   3337 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
   3338 		for(i = 0; i < ipacm_config->ipa_num_alg_ports; i++)
   3339 		{
   3340 			flt_rule_entry.rule.attrib.dst_port = ipacm_config->alg_table[i].port;
   3341 			flt_rule_entry.rule.attrib.u.v4.protocol = ipacm_config->alg_table[i].protocol;
   3342 
   3343 			memset(&flt_eq, 0, sizeof(flt_eq));
   3344 			memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   3345 			flt_eq.ip = iptype;
   3346 			if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   3347 			{
   3348 				IPACMERR("Failed to get eq_attrib\n");
   3349 				res = IPACM_FAILURE;
   3350 				goto fail;
   3351 			}
   3352 
   3353 			memcpy(&flt_rule_entry.rule.eq_attrib,
   3354 						 &flt_eq.eq_attrib,
   3355 						 sizeof(flt_rule_entry.rule.eq_attrib));
   3356 
   3357 			memcpy(&(rules[rule_offset + ipacm_config->ipa_num_alg_ports + 1 + i]),
   3358 				&flt_rule_entry,
   3359 				sizeof(struct ipa_flt_rule_add));
   3360 			IPACM_Wan::num_v4_flt_rule++;
   3361 		}
   3362 		num_rules = IPACM_Wan::num_v4_flt_rule - original_num_rules;
   3363 	}
   3364 	else /* IPv6 case */
   3365 	{
   3366 		original_num_rules = IPACM_Wan::num_v6_flt_rule;
   3367 
   3368 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
   3369 		strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
   3370 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   3371 		rt_tbl_idx.ip = iptype;
   3372 		if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
   3373 		{
   3374 			IPACMERR("Failed to get routing table index from name\n");
   3375 			res = IPACM_FAILURE;
   3376 			goto fail;
   3377 		}
   3378 
   3379 		IPACMDBG_H("WAN DL routing table %s has index %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, rt_tbl_idx.idx);
   3380 
   3381 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   3382 
   3383 		flt_rule_entry.at_rear = true;
   3384 		flt_rule_entry.flt_rule_hdl = -1;
   3385 		flt_rule_entry.status = -1;
   3386 
   3387 		flt_rule_entry.rule.retain_hdr = 1;
   3388 		flt_rule_entry.rule.to_uc = 0;
   3389 		flt_rule_entry.rule.eq_attrib_type = 1;
   3390 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   3391 #ifdef FEATURE_IPA_V3
   3392 		flt_rule_entry.rule.hashable = true;
   3393 #endif
   3394 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
   3395 
   3396 		/* Configuring ICMP filtering rule */
   3397 		memcpy(&flt_rule_entry.rule.attrib,
   3398 					 &rx_prop->rx[1].attrib,
   3399 					 sizeof(flt_rule_entry.rule.attrib));
   3400 		/* Multiple PDNs may exist so keep meta-data */
   3401 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
   3402 		flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6;
   3403 
   3404 		memset(&flt_eq, 0, sizeof(flt_eq));
   3405 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   3406 		flt_eq.ip = iptype;
   3407 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   3408 		{
   3409 			IPACMERR("Failed to get eq_attrib\n");
   3410 			res = IPACM_FAILURE;
   3411 			goto fail;
   3412 		}
   3413 
   3414 		memcpy(&flt_rule_entry.rule.eq_attrib,
   3415 					 &flt_eq.eq_attrib,
   3416 					 sizeof(flt_rule_entry.rule.eq_attrib));
   3417 
   3418 		memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3419 		IPACM_Wan::num_v6_flt_rule++;
   3420 
   3421 		num_rules = IPACM_Wan::num_v6_flt_rule - original_num_rules;
   3422 	}
   3423 
   3424 fail:
   3425 	IPACMDBG_H("Constructed %d ICMP/ALG rules for ip type %d\n", num_rules, iptype);
   3426 		return res;
   3427 }
   3428 
   3429 int IPACM_Wan::query_ext_prop()
   3430 {
   3431 	int fd, ret = IPACM_SUCCESS;
   3432 	uint32_t cnt;
   3433 
   3434 	if (iface_query->num_ext_props > 0)
   3435 	{
   3436 		fd = open(IPA_DEVICE_NAME, O_RDWR);
   3437 		IPACMDBG_H("iface query-property \n");
   3438 		if (0 == fd)
   3439 		{
   3440 			IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
   3441 			return IPACM_FAILURE;
   3442 		}
   3443 
   3444 		ext_prop = (struct ipa_ioc_query_intf_ext_props *)
   3445 			 calloc(1, sizeof(struct ipa_ioc_query_intf_ext_props) +
   3446 							iface_query->num_ext_props * sizeof(struct ipa_ioc_ext_intf_prop));
   3447 		if(ext_prop == NULL)
   3448 		{
   3449 			IPACMERR("Unable to allocate memory.\n");
   3450 			return IPACM_FAILURE;
   3451 		}
   3452 		memcpy(ext_prop->name, dev_name,
   3453 					 sizeof(dev_name));
   3454 		ext_prop->num_ext_props = iface_query->num_ext_props;
   3455 
   3456 		IPACMDBG_H("Query extended property for iface %s\n", ext_prop->name);
   3457 
   3458 		ret = ioctl(fd, IPA_IOC_QUERY_INTF_EXT_PROPS, ext_prop);
   3459 		if (ret < 0)
   3460 		{
   3461 			IPACMERR("ioctl IPA_IOC_QUERY_INTF_EXT_PROPS failed\n");
   3462 			/* ext_prop memory will free when iface-down*/
   3463 			free(ext_prop);
   3464 			close(fd);
   3465 			return ret;
   3466 		}
   3467 
   3468 		IPACMDBG_H("Wan interface has %d tx props, %d rx props and %d ext props\n",
   3469 				iface_query->num_tx_props, iface_query->num_rx_props, iface_query->num_ext_props);
   3470 
   3471 		for (cnt = 0; cnt < ext_prop->num_ext_props; cnt++)
   3472 		{
   3473 #ifndef FEATURE_IPA_V3
   3474 			IPACMDBG_H("Ex(%d): ip-type: %d, mux_id: %d, flt_action: %d\n, rt_tbl_idx: %d, is_xlat_rule: %d flt_hdl: %d\n",
   3475 				cnt, ext_prop->ext[cnt].ip, ext_prop->ext[cnt].mux_id, ext_prop->ext[cnt].action,
   3476 				ext_prop->ext[cnt].rt_tbl_idx, ext_prop->ext[cnt].is_xlat_rule, ext_prop->ext[cnt].filter_hdl);
   3477 #else /* defined (FEATURE_IPA_V3) */
   3478 			IPACMDBG_H("Ex(%d): ip-type: %d, mux_id: %d, flt_action: %d\n, rt_tbl_idx: %d, is_xlat_rule: %d rule_id: %d\n",
   3479 				cnt, ext_prop->ext[cnt].ip, ext_prop->ext[cnt].mux_id, ext_prop->ext[cnt].action,
   3480 				ext_prop->ext[cnt].rt_tbl_idx, ext_prop->ext[cnt].is_xlat_rule, ext_prop->ext[cnt].rule_id);
   3481 #endif
   3482 		}
   3483 
   3484 		if(IPACM_Wan::is_ext_prop_set == false)
   3485 		{
   3486 			IPACM_Iface::ipacmcfg->SetExtProp(ext_prop);
   3487 			IPACM_Wan::is_ext_prop_set = true;
   3488 		}
   3489 		close(fd);
   3490 	}
   3491 	return IPACM_SUCCESS;
   3492 }
   3493 
   3494 int IPACM_Wan::config_wan_firewall_rule(ipa_ip_type iptype)
   3495 {
   3496 	int res = IPACM_SUCCESS;
   3497 
   3498 	IPACMDBG_H("Configure WAN DL firewall rules.\n");
   3499 
   3500 	if(iptype == IPA_IP_v4)
   3501 	{
   3502 		IPACM_Wan::num_v4_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4;
   3503 		if(IPACM_FAILURE == add_icmp_alg_rules(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4))
   3504 		{
   3505 			IPACMERR("Failed to add ICMP and ALG port filtering rules.\n");
   3506 			res = IPACM_FAILURE;
   3507 			goto fail;
   3508 		}
   3509 		IPACMDBG_H("Succeded in constructing ICMP/ALG rules for ip type %d\n", iptype);
   3510 
   3511 		if(IPACM_FAILURE == config_dft_firewall_rules_ex(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4))
   3512 		{
   3513 			IPACMERR("Failed to add firewall filtering rules.\n");
   3514 			res = IPACM_FAILURE;
   3515 			goto fail;
   3516 		}
   3517 		IPACMDBG_H("Succeded in constructing firewall rules for ip type %d\n", iptype);
   3518 	}
   3519 	else if(iptype == IPA_IP_v6)
   3520 	{
   3521 		IPACM_Wan::num_v6_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6;
   3522 		if(IPACM_FAILURE == add_icmp_alg_rules(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6))
   3523 		{
   3524 			IPACMERR("Failed to add ICMP and ALG port filtering rules.\n");
   3525 			res = IPACM_FAILURE;
   3526 			goto fail;
   3527 		}
   3528 		IPACMDBG_H("Succeded in constructing ICMP/ALG rules for ip type %d\n", iptype);
   3529 
   3530 		if(IPACM_FAILURE == config_dft_firewall_rules_ex(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6))
   3531 		{
   3532 			IPACMERR("Failed to add firewall filtering rules.\n");
   3533 			res = IPACM_FAILURE;
   3534 			goto fail;
   3535 		}
   3536 		IPACMDBG_H("Succeded in constructing firewall rules for ip type %d\n", iptype);
   3537 	}
   3538 	else
   3539 	{
   3540 		IPACMERR("IP type is not expected.\n");
   3541 		return IPACM_FAILURE;
   3542 	}
   3543 
   3544 fail:
   3545 	return res;
   3546 }
   3547 
   3548 int IPACM_Wan::add_dft_filtering_rule(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype)
   3549 {
   3550 	struct ipa_ioc_get_rt_tbl_indx rt_tbl_idx;
   3551 	struct ipa_flt_rule_add flt_rule_entry;
   3552 	struct ipa_ioc_generate_flt_eq flt_eq;
   3553 	int res = IPACM_SUCCESS;
   3554 
   3555 	if(rules == NULL)
   3556 	{
   3557 		IPACMERR("No filtering table available.\n");
   3558 		return IPACM_FAILURE;
   3559 	}
   3560 	if(rx_prop == NULL)
   3561 	{
   3562 		IPACMERR("No tx property.\n");
   3563 		return IPACM_FAILURE;
   3564 	}
   3565 
   3566 	if (iptype == IPA_IP_v4)
   3567 	{
   3568 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
   3569 		strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
   3570 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   3571 		rt_tbl_idx.ip = iptype;
   3572 		if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
   3573 		{
   3574 			IPACMERR("Failed to get routing table index from name\n");
   3575 			res = IPACM_FAILURE;
   3576 			goto fail;
   3577 		}
   3578 
   3579 		IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
   3580 
   3581 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   3582 
   3583 		flt_rule_entry.at_rear = true;
   3584 		flt_rule_entry.flt_rule_hdl = -1;
   3585 		flt_rule_entry.status = -1;
   3586 
   3587 		flt_rule_entry.rule.retain_hdr = 1;
   3588 		flt_rule_entry.rule.to_uc = 0;
   3589 		flt_rule_entry.rule.eq_attrib_type = 1;
   3590 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   3591 #ifdef FEATURE_IPA_V3
   3592 		flt_rule_entry.rule.hashable = true;
   3593 #endif
   3594 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
   3595 
   3596 		IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
   3597 
   3598 		/* Configuring Multicast Filtering Rule */
   3599 		memcpy(&flt_rule_entry.rule.attrib,
   3600 					 &rx_prop->rx[0].attrib,
   3601 					 sizeof(flt_rule_entry.rule.attrib));
   3602 		/* remove meta data mask since we only install default flt rules once for all modem PDN*/
   3603 		flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA);
   3604 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   3605 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xF0000000;
   3606 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000;
   3607 
   3608 		change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib);
   3609 
   3610 		memset(&flt_eq, 0, sizeof(flt_eq));
   3611 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   3612 		flt_eq.ip = iptype;
   3613 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   3614 		{
   3615 			IPACMERR("Failed to get eq_attrib\n");
   3616 			res = IPACM_FAILURE;
   3617 			goto fail;
   3618 		}
   3619 
   3620 		memcpy(&flt_rule_entry.rule.eq_attrib,
   3621 					 &flt_eq.eq_attrib,
   3622 					 sizeof(flt_rule_entry.rule.eq_attrib));
   3623 		memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3624 
   3625 		/* Configuring Broadcast Filtering Rule */
   3626 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
   3627 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF;
   3628 
   3629 		change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib);
   3630 
   3631 		memset(&flt_eq, 0, sizeof(flt_eq));
   3632 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   3633 		flt_eq.ip = iptype;
   3634 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   3635 		{
   3636 			IPACMERR("Failed to get eq_attrib\n");
   3637 			res = IPACM_FAILURE;
   3638 			goto fail;
   3639 		}
   3640 
   3641 		memcpy(&flt_rule_entry.rule.eq_attrib,
   3642 					 &flt_eq.eq_attrib,
   3643 					 sizeof(flt_rule_entry.rule.eq_attrib));
   3644 		memcpy(&(rules[rule_offset + 1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3645 
   3646 		IPACM_Wan::num_v4_flt_rule += IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4;
   3647 		IPACMDBG_H("Constructed %d default filtering rules for ip type %d\n", IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4, iptype);
   3648 	}
   3649 	else	/*insert rules for ipv6*/
   3650 	{
   3651 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
   3652 		strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
   3653 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   3654 		rt_tbl_idx.ip = iptype;
   3655 		if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
   3656 		{
   3657 			IPACMERR("Failed to get routing table index from name\n");
   3658 			res = IPACM_FAILURE;
   3659 			goto fail;
   3660 		}
   3661 
   3662 		IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
   3663 
   3664 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   3665 
   3666 		flt_rule_entry.at_rear = true;
   3667 		flt_rule_entry.flt_rule_hdl = -1;
   3668 		flt_rule_entry.status = -1;
   3669 
   3670 		flt_rule_entry.rule.retain_hdr = 1;
   3671 		flt_rule_entry.rule.to_uc = 0;
   3672 		flt_rule_entry.rule.eq_attrib_type = 1;
   3673 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   3674 #ifdef FEATURE_IPA_V3
   3675 		flt_rule_entry.rule.hashable = true;
   3676 #endif
   3677 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
   3678 
   3679 		/* Configuring Multicast Filtering Rule */
   3680 		memcpy(&flt_rule_entry.rule.attrib,
   3681 					 &rx_prop->rx[0].attrib,
   3682 					 sizeof(flt_rule_entry.rule.attrib));
   3683 		/* remove meta data mask since we only install default flt rules once for all modem PDN*/
   3684 		flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA);
   3685 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   3686 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
   3687 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
   3688 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
   3689 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
   3690 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFF000000;
   3691 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
   3692 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
   3693 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0x00000000;
   3694 
   3695 		change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
   3696 
   3697 		memset(&flt_eq, 0, sizeof(flt_eq));
   3698 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   3699 		flt_eq.ip = iptype;
   3700 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   3701 		{
   3702 			IPACMERR("Failed to get eq_attrib\n");
   3703 			res = IPACM_FAILURE;
   3704 			goto fail;
   3705 		}
   3706 
   3707 		memcpy(&flt_rule_entry.rule.eq_attrib,
   3708 					 &flt_eq.eq_attrib,
   3709 					 sizeof(flt_rule_entry.rule.eq_attrib));
   3710 		memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3711 
   3712 		/* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */
   3713 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFC00000;
   3714 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
   3715 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
   3716 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
   3717 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFE800000;
   3718 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
   3719 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
   3720 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0x00000000;
   3721 
   3722 		change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
   3723 
   3724 		memset(&flt_eq, 0, sizeof(flt_eq));
   3725 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   3726 		flt_eq.ip = iptype;
   3727 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   3728 		{
   3729 			IPACMERR("Failed to get eq_attrib\n");
   3730 			res = IPACM_FAILURE;
   3731 			goto fail;
   3732 		}
   3733 
   3734 		memcpy(&flt_rule_entry.rule.eq_attrib,
   3735 					 &flt_eq.eq_attrib,
   3736 					 sizeof(flt_rule_entry.rule.eq_attrib));
   3737 
   3738 		memcpy(&(rules[rule_offset + 1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3739 
   3740 		/* Configuring fec0::/10 Reserved by IETF Filtering Rule */
   3741 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFC00000;
   3742 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
   3743 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
   3744 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
   3745 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFEC00000;
   3746 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
   3747 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
   3748 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0x00000000;
   3749 
   3750 		change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
   3751 
   3752 		memset(&flt_eq, 0, sizeof(flt_eq));
   3753 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   3754 		flt_eq.ip = iptype;
   3755 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   3756 		{
   3757 			IPACMERR("Failed to get eq_attrib\n");
   3758 			res = IPACM_FAILURE;
   3759 			goto fail;
   3760 		}
   3761 
   3762 		memcpy(&flt_rule_entry.rule.eq_attrib,
   3763 					 &flt_eq.eq_attrib,
   3764 					 sizeof(flt_rule_entry.rule.eq_attrib));
   3765 
   3766 		memcpy(&(rules[rule_offset + 2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3767 
   3768 #ifdef FEATURE_IPA_ANDROID
   3769 		IPACMDBG_H("Add TCP ctrl rules: total num %d\n", IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6);
   3770 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   3771 
   3772 		flt_rule_entry.at_rear = true;
   3773 		flt_rule_entry.flt_rule_hdl = -1;
   3774 		flt_rule_entry.status = -1;
   3775 
   3776 		flt_rule_entry.rule.retain_hdr = 1;
   3777 		flt_rule_entry.rule.to_uc = 0;
   3778 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   3779 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
   3780 		flt_rule_entry.rule.eq_attrib_type = 1;
   3781 
   3782 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap = 0;
   3783 
   3784 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<1);
   3785 		flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1;
   3786 		flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP;
   3787 
   3788 #ifdef FEATURE_IPA_V3
   3789 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7);
   3790 #else
   3791 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8);
   3792 #endif
   3793 		flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1;
   3794 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12;
   3795 
   3796 		/* add TCP FIN rule*/
   3797 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_FIN_SHIFT);
   3798 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_FIN_SHIFT);
   3799 		memcpy(&(rules[rule_offset + 3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3800 
   3801 		/* add TCP SYN rule*/
   3802 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_SYN_SHIFT);
   3803 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_SYN_SHIFT);
   3804 		memcpy(&(rules[rule_offset + 4]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3805 
   3806 		/* add TCP RST rule*/
   3807 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_RST_SHIFT);
   3808 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_RST_SHIFT);
   3809 		memcpy(&(rules[rule_offset + 5]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3810 #endif
   3811 
   3812 		IPACM_Wan::num_v6_flt_rule += IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6;
   3813 		IPACMDBG_H("Constructed %d default filtering rules for ip type %d\n", IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6, iptype);
   3814 	}
   3815 
   3816 fail:
   3817 	return res;
   3818 }
   3819 
   3820 int IPACM_Wan::del_wan_firewall_rule(ipa_ip_type iptype)
   3821 {
   3822 	if(iptype == IPA_IP_v4)
   3823 	{
   3824 		IPACM_Wan::num_v4_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4;
   3825 		memset(&IPACM_Wan::flt_rule_v4[IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4], 0,
   3826 			(IPA_MAX_FLT_RULE - IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4) * sizeof(struct ipa_flt_rule_add));
   3827 	}
   3828 	else if(iptype == IPA_IP_v6)
   3829 	{
   3830 		IPACM_Wan::num_v6_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6;
   3831 		memset(&IPACM_Wan::flt_rule_v6[IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6], 0,
   3832 			(IPA_MAX_FLT_RULE - IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6) * sizeof(struct ipa_flt_rule_add));
   3833 	}
   3834 	else
   3835 	{
   3836 		IPACMERR("IP type is not expected.\n");
   3837 		return IPACM_FAILURE;
   3838 	}
   3839 
   3840 	return IPACM_SUCCESS;
   3841 }
   3842 
   3843 /*for STA mode: clean firewall filter rules */
   3844 int IPACM_Wan::del_dft_firewall_rules(ipa_ip_type iptype)
   3845 {
   3846 	/* free v4 firewall filter rule */
   3847 	if (rx_prop == NULL)
   3848 	{
   3849 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
   3850 		return IPACM_SUCCESS;
   3851 	}
   3852 
   3853 	if ((iptype == IPA_IP_v4) && (active_v4 == true))
   3854 	{
   3855 		if (num_firewall_v4 > IPACM_MAX_FIREWALL_ENTRIES)
   3856 		{
   3857 			IPACMERR("the number of v4 firewall entries overflow, aborting...\n");
   3858 			return IPACM_FAILURE;
   3859 		}
   3860 		if (num_firewall_v4 != 0)
   3861 		{
   3862 			if (m_filtering.DeleteFilteringHdls(firewall_hdl_v4,
   3863 																					IPA_IP_v4, num_firewall_v4) == false)
   3864 			{
   3865 				IPACMERR("Error Deleting Filtering rules, aborting...\n");
   3866 				return IPACM_FAILURE;
   3867 			}
   3868 			IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, num_firewall_v4);
   3869 		}
   3870 		else
   3871 		{
   3872 			IPACMDBG_H("No ipv4 firewall rules, no need deleted\n");
   3873 		}
   3874 
   3875 		if (m_filtering.DeleteFilteringHdls(dft_wan_fl_hdl,
   3876 																				IPA_IP_v4, 1) == false)
   3877 		{
   3878 			IPACMERR("Error Deleting Filtering rules, aborting...\n");
   3879 			return IPACM_FAILURE;
   3880 		}
   3881 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
   3882 
   3883 		num_firewall_v4 = 0;
   3884 	}
   3885 
   3886 	/* free v6 firewall filter rule */
   3887 	if ((iptype == IPA_IP_v6) && (active_v6 == true))
   3888 	{
   3889 		if (num_firewall_v6 > IPACM_MAX_FIREWALL_ENTRIES)
   3890 		{
   3891 			IPACMERR("the number of v6 firewall entries overflow, aborting...\n");
   3892 			return IPACM_FAILURE;
   3893 		}
   3894 		if (num_firewall_v6 != 0)
   3895 		{
   3896 			if (m_filtering.DeleteFilteringHdls(firewall_hdl_v6,
   3897 																					IPA_IP_v6, num_firewall_v6) == false)
   3898 			{
   3899 				IPACMERR("Error Deleting Filtering rules, aborting...\n");
   3900 				return IPACM_FAILURE;
   3901 			}
   3902 			IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, num_firewall_v6);
   3903 		}
   3904 		else
   3905 		{
   3906 			IPACMDBG_H("No ipv6 firewall rules, no need deleted\n");
   3907 		}
   3908 
   3909 		if (m_filtering.DeleteFilteringHdls(&dft_wan_fl_hdl[1],
   3910 																				IPA_IP_v6, 1) == false)
   3911 		{
   3912 			IPACMERR("Error Deleting Filtering rules, aborting...\n");
   3913 			return IPACM_FAILURE;
   3914 		}
   3915 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
   3916 		if (m_filtering.DeleteFilteringHdls(&dft_wan_fl_hdl[2],
   3917 																				IPA_IP_v6, 1) == false)
   3918 		{
   3919 			IPACMERR("Error Deleting Filtering rules, aborting...\n");
   3920 			return IPACM_FAILURE;
   3921 		}
   3922 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
   3923 
   3924 		if (is_ipv6_frag_firewall_flt_rule_installed &&
   3925 			check_dft_firewall_rules_attr_mask(&firewall_config))
   3926 		{
   3927 			if (m_filtering.DeleteFilteringHdls(&ipv6_frag_firewall_flt_rule_hdl, IPA_IP_v6, 1) == false)
   3928 			{
   3929 				IPACMERR("Error deleting IPv6 frag filtering rules.\n");
   3930 				return IPACM_FAILURE;
   3931 			}
   3932 			is_ipv6_frag_firewall_flt_rule_installed = false;
   3933 			IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
   3934 		}
   3935 		num_firewall_v6 = 0;
   3936 	}
   3937 
   3938 	return IPACM_SUCCESS;
   3939 }
   3940 
   3941 /* for STA mode: wan default route/filter rule delete */
   3942 int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype)
   3943 {
   3944 	uint32_t tx_index;
   3945 	ipacm_cmd_q_data evt_data;
   3946 
   3947 	IPACMDBG_H("got handle_route_del_evt for STA-mode with ip-family:%d \n", iptype);
   3948 
   3949 	if(tx_prop == NULL)
   3950 	{
   3951 		IPACMDBG_H("No tx properties, ignore delete default route setting\n");
   3952 		return IPACM_SUCCESS;
   3953 	}
   3954 
   3955 	is_default_gateway = false;
   3956 	IPACMDBG_H("Default route is deleted to iface %s.\n", dev_name);
   3957 
   3958 	if (((iptype == IPA_IP_v4) && (active_v4 == true)) ||
   3959 			((iptype == IPA_IP_v6) && (active_v6 == true)))
   3960 	{
   3961 
   3962 		/* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */
   3963 		IPACMDBG_H("dev %s add producer dependency\n", dev_name);
   3964 		IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
   3965 		IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
   3966 
   3967 		for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
   3968 		{
   3969 		    if(iptype != tx_prop->tx[tx_index].ip)
   3970 		    {
   3971 		    	IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d, no RT-rule deleted\n",
   3972 		    					    tx_index, tx_prop->tx[tx_index].ip,iptype);
   3973 		    	continue;
   3974 		    }
   3975 
   3976 			if (iptype == IPA_IP_v4)
   3977 			{
   3978 		    	IPACMDBG_H("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n", tx_index, tx_prop->tx[tx_index].ip,iptype);
   3979 
   3980 				if (m_routing.DeleteRoutingHdl(wan_route_rule_v4_hdl[tx_index], IPA_IP_v4) == false)
   3981 				{
   3982 					IPACMDBG_H("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v4, wan_route_rule_v4_hdl[tx_index], tx_index);
   3983 					return IPACM_FAILURE;
   3984 				}
   3985 			}
   3986 			else
   3987 			{
   3988 		    	IPACMDBG_H("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n", tx_index, tx_prop->tx[tx_index].ip,iptype);
   3989 
   3990 				if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl[tx_index], IPA_IP_v6) == false)
   3991 				{
   3992 					IPACMDBG_H("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v6, wan_route_rule_v6_hdl[tx_index], tx_index);
   3993 					return IPACM_FAILURE;
   3994 				}
   3995 			}
   3996 		}
   3997 
   3998 		/* Delete the default wan route*/
   3999 		if (iptype == IPA_IP_v6)
   4000 		{
   4001 		   	IPACMDBG_H("ip-type %d: default v6 wan RT-rule deleted\n",iptype);
   4002 			if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl_a5[0], IPA_IP_v6) == false)
   4003 			{
   4004 			IPACMDBG_H("IP-family:%d, Routing rule(hdl:0x%x) deletion failed!\n",IPA_IP_v6,wan_route_rule_v6_hdl_a5[0]);
   4005 				return IPACM_FAILURE;
   4006 			}
   4007 		}
   4008 		ipacm_event_iface_up *wandown_data;
   4009 		wandown_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up));
   4010 		if (wandown_data == NULL)
   4011 		{
   4012 			IPACMERR("Unable to allocate memory\n");
   4013 			return IPACM_FAILURE;
   4014 		}
   4015 		memset(wandown_data, 0, sizeof(ipacm_event_iface_up));
   4016 
   4017 		if (iptype == IPA_IP_v4)
   4018 		{
   4019 			wandown_data->ipv4_addr = wan_v4_addr;
   4020 			if (m_is_sta_mode!=Q6_WAN)
   4021 			{
   4022 				wandown_data->is_sta = true;
   4023 			}
   4024 			else
   4025 			{
   4026 				wandown_data->is_sta = false;
   4027 			}
   4028 			evt_data.event = IPA_HANDLE_WAN_DOWN;
   4029 			evt_data.evt_data = (void *)wandown_data;
   4030 			/* Insert IPA_HANDLE_WAN_DOWN to command queue */
   4031 			IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN for IPv4 (%d.%d.%d.%d) \n",
   4032 					(unsigned char)(wandown_data->ipv4_addr),
   4033 					(unsigned char)(wandown_data->ipv4_addr >> 8),
   4034 					(unsigned char)(wandown_data->ipv4_addr >> 16),
   4035 					(unsigned char)(wandown_data->ipv4_addr >> 24));
   4036 
   4037 			IPACM_EvtDispatcher::PostEvt(&evt_data);
   4038 			IPACMDBG_H("setup wan_up/active_v4= false \n");
   4039 			IPACM_Wan::wan_up = false;
   4040 			active_v4 = false;
   4041 			if(IPACM_Wan::wan_up_v6)
   4042 			{
   4043 				IPACMDBG_H("modem v6-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name);
   4044 			}
   4045 			else
   4046 			{
   4047 				memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name));
   4048 			}
   4049 		}
   4050 		else
   4051 		{
   4052 			if (m_is_sta_mode!=Q6_WAN)
   4053 			{
   4054 				wandown_data->is_sta = true;
   4055 			}
   4056 			else
   4057 			{
   4058 				wandown_data->is_sta = false;
   4059 			}
   4060 			memcpy(wandown_data->ipv6_prefix, ipv6_prefix, sizeof(wandown_data->ipv6_prefix));
   4061 			evt_data.event = IPA_HANDLE_WAN_DOWN_V6;
   4062 			evt_data.evt_data = (void *)wandown_data;
   4063 			/* Insert IPA_HANDLE_WAN_DOWN to command queue */
   4064 			IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN for IPv6 with prefix 0x%08x%08x\n", ipv6_prefix[0], ipv6_prefix[1]);
   4065 			IPACM_EvtDispatcher::PostEvt(&evt_data);
   4066 			IPACMDBG_H("setup wan_up_v6/active_v6= false \n");
   4067 			IPACM_Wan::wan_up_v6 = false;
   4068 			active_v6 = false;
   4069 			if(IPACM_Wan::wan_up)
   4070 			{
   4071 				IPACMDBG_H("modem v4-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name);
   4072 			}
   4073 			else
   4074 			{
   4075 				memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name));
   4076 			}
   4077 		}
   4078 	}
   4079 	else
   4080 	{
   4081 		IPACMDBG_H(" The default WAN routing rules are deleted already \n");
   4082 	}
   4083 
   4084 	return IPACM_SUCCESS;
   4085 }
   4086 
   4087 int IPACM_Wan::handle_route_del_evt_ex(ipa_ip_type iptype)
   4088 {
   4089 	ipacm_cmd_q_data evt_data;
   4090 
   4091 	IPACMDBG_H("got handle_route_del_evt_ex with ip-family:%d \n", iptype);
   4092 
   4093 	if(tx_prop == NULL)
   4094 	{
   4095 		IPACMDBG_H("No tx properties, ignore delete default route setting\n");
   4096 		return IPACM_SUCCESS;
   4097 	}
   4098 
   4099 	is_default_gateway = false;
   4100 	IPACMDBG_H("Default route is deleted to iface %s.\n", dev_name);
   4101 
   4102 	if (((iptype == IPA_IP_v4) && (active_v4 == true)) ||
   4103 		((iptype == IPA_IP_v6) && (active_v6 == true)))
   4104 	{
   4105 
   4106 		/* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */
   4107 		IPACMDBG_H("dev %s add producer dependency\n", dev_name);
   4108 		IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
   4109 		IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
   4110 
   4111 		/* Delete the default route*/
   4112 		if (iptype == IPA_IP_v6)
   4113 		{
   4114 			IPACMDBG_H("ip-type %d: default v6 wan RT-rule deleted\n",iptype);
   4115 			if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl_a5[0], IPA_IP_v6) == false)
   4116 			{
   4117 				IPACMDBG_H("IP-family:%d, Routing rule(hdl:0x%x) deletion failed!\n",IPA_IP_v6,wan_route_rule_v6_hdl_a5[0]);
   4118 				return IPACM_FAILURE;
   4119 			}
   4120 		}
   4121 
   4122 		ipacm_event_iface_up *wandown_data;
   4123 		wandown_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up));
   4124 		if (wandown_data == NULL)
   4125 		{
   4126 			IPACMERR("Unable to allocate memory\n");
   4127 			return IPACM_FAILURE;
   4128 		}
   4129 		memset(wandown_data, 0, sizeof(ipacm_event_iface_up));
   4130 
   4131 		if (iptype == IPA_IP_v4)
   4132 		{
   4133 			wandown_data->ipv4_addr = wan_v4_addr;
   4134 			if (m_is_sta_mode!=Q6_WAN)
   4135 			{
   4136 				wandown_data->is_sta = true;
   4137 			}
   4138 			else
   4139 			{
   4140 				wandown_data->is_sta = false;
   4141 			}
   4142 			evt_data.event = IPA_HANDLE_WAN_DOWN;
   4143 			evt_data.evt_data = (void *)wandown_data;
   4144 			/* Insert IPA_HANDLE_WAN_DOWN to command queue */
   4145 			IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN for IPv4 with address: 0x%x\n", wan_v4_addr);
   4146 			IPACM_EvtDispatcher::PostEvt(&evt_data);
   4147 
   4148 			IPACMDBG_H("setup wan_up/active_v4= false \n");
   4149 			IPACM_Wan::wan_up = false;
   4150 			active_v4 = false;
   4151 			if(IPACM_Wan::wan_up_v6)
   4152 			{
   4153 				IPACMDBG_H("modem v6-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name);
   4154 			}
   4155 			else
   4156 			{
   4157 				memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name));
   4158 			}
   4159 		}
   4160 		else
   4161 		{
   4162 			if (m_is_sta_mode!=Q6_WAN)
   4163 			{
   4164 				wandown_data->is_sta = true;
   4165 			}
   4166 			else
   4167 			{
   4168 				wandown_data->is_sta = false;
   4169 			}
   4170 			memcpy(wandown_data->ipv6_prefix, ipv6_prefix, sizeof(wandown_data->ipv6_prefix));
   4171 			evt_data.event = IPA_HANDLE_WAN_DOWN_V6;
   4172 			evt_data.evt_data = (void *)wandown_data;
   4173 			IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN_V6 for IPv6 with prefix 0x%08x%08x\n", ipv6_prefix[0], ipv6_prefix[1]);
   4174 			IPACM_EvtDispatcher::PostEvt(&evt_data);
   4175 
   4176 			IPACMDBG_H("setup wan_up_v6/active_v6= false \n");
   4177 			IPACM_Wan::wan_up_v6 = false;
   4178 			active_v6 = false;
   4179 			if(IPACM_Wan::wan_up)
   4180 			{
   4181 				IPACMDBG_H("modem v4-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name);
   4182 			}
   4183 			else
   4184 			{
   4185 				memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name));
   4186 			}
   4187 		}
   4188 	}
   4189 	else
   4190 	{
   4191 		IPACMDBG_H(" The default WAN routing rules are deleted already \n");
   4192 	}
   4193 
   4194 	return IPACM_SUCCESS;
   4195 }
   4196 
   4197 /* configure the initial embms filter rules */
   4198 int IPACM_Wan::config_dft_embms_rules(ipa_ioc_add_flt_rule *pFilteringTable_v4, ipa_ioc_add_flt_rule *pFilteringTable_v6)
   4199 {
   4200 	struct ipa_flt_rule_add flt_rule_entry;
   4201 	struct ipa_ioc_get_rt_tbl_indx rt_tbl_idx;
   4202 	struct ipa_ioc_generate_flt_eq flt_eq;
   4203 
   4204 	if (rx_prop == NULL)
   4205 	{
   4206 		IPACMDBG("No rx properties registered for iface %s\n", dev_name);
   4207 		return IPACM_SUCCESS;
   4208 	}
   4209 
   4210 	if(pFilteringTable_v4 == NULL || pFilteringTable_v6 == NULL)
   4211 	{
   4212 		IPACMERR("Either v4 or v6 filtering table is empty.\n");
   4213 		return IPACM_FAILURE;
   4214 	}
   4215 
   4216 	/* set up ipv4 odu rule*/
   4217 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   4218 
   4219 	/* get eMBMS ODU tbl index*/
   4220 	memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
   4221 	strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v4.name, IPA_RESOURCE_NAME_MAX);
   4222 	rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   4223 	rt_tbl_idx.ip = IPA_IP_v4;
   4224 	if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
   4225 	{
   4226 		IPACMERR("Failed to get routing table index from name\n");
   4227 		return IPACM_FAILURE;
   4228 	}
   4229 	IPACMDBG_H("Odu routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
   4230 
   4231 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   4232 	flt_rule_entry.flt_rule_hdl = -1;
   4233 	flt_rule_entry.status = -1;
   4234 	flt_rule_entry.at_rear = false;
   4235 
   4236 	flt_rule_entry.rule.retain_hdr = 0;
   4237 	flt_rule_entry.rule.to_uc = 0;
   4238 	flt_rule_entry.rule.eq_attrib_type = 1;
   4239 	flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   4240 #ifdef FEATURE_IPA_V3
   4241 	flt_rule_entry.rule.hashable = true;
   4242 #endif
   4243 	flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
   4244 
   4245 	memcpy(&flt_rule_entry.rule.attrib,
   4246 				 &rx_prop->rx[0].attrib,
   4247 				 sizeof(struct ipa_rule_attrib));
   4248 	flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   4249 	flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000;
   4250 	flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000;
   4251 
   4252 	memset(&flt_eq, 0, sizeof(flt_eq));
   4253 	memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   4254 	flt_eq.ip = IPA_IP_v4;
   4255 	if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   4256 	{
   4257 		IPACMERR("Failed to get eq_attrib\n");
   4258 		return IPACM_FAILURE;
   4259 	}
   4260 	memcpy(&flt_rule_entry.rule.eq_attrib,
   4261 				 &flt_eq.eq_attrib,
   4262 				 sizeof(flt_rule_entry.rule.eq_attrib));
   4263 
   4264 	memcpy(&(pFilteringTable_v4->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   4265 
   4266 	/* construc v6 rule */
   4267 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   4268 	/* get eMBMS ODU tbl*/
   4269 	memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
   4270 	strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v6.name, IPA_RESOURCE_NAME_MAX);
   4271 	rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   4272 	rt_tbl_idx.ip = IPA_IP_v6;
   4273 	if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
   4274 	{
   4275 		IPACMERR("Failed to get routing table index from name\n");
   4276 		return IPACM_FAILURE;
   4277 	}
   4278 	IPACMDBG_H("Odu routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
   4279 
   4280 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   4281 	flt_rule_entry.flt_rule_hdl = -1;
   4282 	flt_rule_entry.status = -1;
   4283 	flt_rule_entry.at_rear = false;
   4284 
   4285 	flt_rule_entry.rule.retain_hdr = 0;
   4286 	flt_rule_entry.rule.to_uc = 0;
   4287 	flt_rule_entry.rule.eq_attrib_type = 1;
   4288 	flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   4289 #ifdef FEATURE_IPA_V3
   4290 	flt_rule_entry.rule.hashable = true;
   4291 #endif
   4292 	flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
   4293 
   4294 	memcpy(&flt_rule_entry.rule.attrib,
   4295 				 &rx_prop->rx[0].attrib,
   4296 				 sizeof(struct ipa_rule_attrib));
   4297 	flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   4298 	flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;
   4299 	flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
   4300 	flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
   4301 	flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
   4302 	flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000;
   4303 	flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
   4304 	flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
   4305 	flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
   4306 
   4307 	memset(&flt_eq, 0, sizeof(flt_eq));
   4308 	memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   4309 	flt_eq.ip = IPA_IP_v6;
   4310 	if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   4311 	{
   4312 		IPACMERR("Failed to get eq_attrib\n");
   4313 		return IPACM_FAILURE;
   4314 	}
   4315 	memcpy(&flt_rule_entry.rule.eq_attrib,
   4316 				 &flt_eq.eq_attrib,
   4317 				 sizeof(flt_rule_entry.rule.eq_attrib));
   4318 
   4319 	memcpy(&(pFilteringTable_v6->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   4320 
   4321 	return IPACM_SUCCESS;
   4322 }
   4323 
   4324 
   4325 /*for STA mode: handle wan-iface down event */
   4326 int IPACM_Wan::handle_down_evt()
   4327 {
   4328 	int res = IPACM_SUCCESS;
   4329 	uint32_t i;
   4330 
   4331 	IPACMDBG_H(" wan handle_down_evt \n");
   4332 
   4333 	/* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */
   4334 	IPACMDBG_H("dev %s add producer dependency\n", dev_name);
   4335 	if (tx_prop != NULL)
   4336 	{
   4337 		IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
   4338 		IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
   4339 	}
   4340 
   4341 	/* no iface address up, directly close iface*/
   4342 	if (ip_type == IPACM_IP_NULL)
   4343 	{
   4344 		goto fail;
   4345 	}
   4346 
   4347 	/* make sure default routing rules and firewall rules are deleted*/
   4348 	if (active_v4)
   4349 	{
   4350 	   	if (rx_prop != NULL)
   4351 	    {
   4352 			del_dft_firewall_rules(IPA_IP_v4);
   4353 		}
   4354 		handle_route_del_evt(IPA_IP_v4);
   4355 		IPACMDBG_H("Delete default v4 routing rules\n");
   4356 	}
   4357 
   4358 	if (active_v6)
   4359 	{
   4360 	   	if (rx_prop != NULL)
   4361 	    {
   4362 			del_dft_firewall_rules(IPA_IP_v6);
   4363 		}
   4364 		handle_route_del_evt(IPA_IP_v6);
   4365 		IPACMDBG_H("Delete default v6 routing rules\n");
   4366 	}
   4367 
   4368 	/* Delete default v4 RT rule */
   4369 	if (ip_type != IPA_IP_v6)
   4370 	{
   4371 		IPACMDBG_H("Delete default v4 routing rules\n");
   4372 		if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
   4373 		{
   4374 		   IPACMERR("Routing rule deletion failed!\n");
   4375 			res = IPACM_FAILURE;
   4376 			goto fail;
   4377 		}
   4378 	}
   4379 
   4380 	/* delete default v6 RT rule */
   4381 	if (ip_type != IPA_IP_v4)
   4382 	{
   4383 		IPACMDBG_H("Delete default v6 routing rules\n");
   4384 		/* May have multiple ipv6 iface-routing rules*/
   4385 		for (i = 0; i < 2*num_dft_rt_v6; i++)
   4386 		{
   4387 			if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
   4388 			{
   4389 				IPACMERR("Routing rule deletion failed!\n");
   4390 				res = IPACM_FAILURE;
   4391 				goto fail;
   4392 			}
   4393 		}
   4394 
   4395 		IPACMDBG_H("finished delete default v6 RT rules\n ");
   4396 	}
   4397 
   4398 
   4399 	/* clean wan-client header, routing rules */
   4400 	IPACMDBG_H("left %d wan clients need to be deleted \n ", num_wan_client);
   4401 	for (i = 0; i < num_wan_client; i++)
   4402 	{
   4403 			/* Del NAT rules before ipv4 RT rules are delete */
   4404 			if(get_client_memptr(wan_client, i)->ipv4_set == true)
   4405 			{
   4406 				IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wan_client, i)->v4_addr);
   4407 				CtList->HandleSTAClientDelEvt(get_client_memptr(wan_client, i)->v4_addr);
   4408 			}
   4409 
   4410 			if (delete_wan_rtrules(i, IPA_IP_v4))
   4411 			{
   4412 				IPACMERR("unbale to delete wan-client v4 route rules for index %d\n", i);
   4413 				res = IPACM_FAILURE;
   4414 				goto fail;
   4415 			}
   4416 
   4417 			if (delete_wan_rtrules(i, IPA_IP_v6))
   4418 			{
   4419 				IPACMERR("unbale to delete ecm-client v6 route rules for index %d\n", i);
   4420 				res = IPACM_FAILURE;
   4421 				goto fail;
   4422 			}
   4423 
   4424 			IPACMDBG_H("Delete %d client header\n", num_wan_client);
   4425 
   4426 
   4427 			if(get_client_memptr(wan_client, i)->ipv4_header_set == true)
   4428 			{
   4429 				if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, i)->hdr_hdl_v4)
   4430 					== false)
   4431 				{
   4432 					res = IPACM_FAILURE;
   4433 					goto fail;
   4434 				}
   4435 			}
   4436 
   4437 			if(get_client_memptr(wan_client, i)->ipv6_header_set == true)
   4438 			{
   4439 			if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, i)->hdr_hdl_v6)
   4440 					== false)
   4441 			{
   4442 				res = IPACM_FAILURE;
   4443 				goto fail;
   4444 			}
   4445 			}
   4446 	} /* end of for loop */
   4447 
   4448 	/* free the edm clients cache */
   4449 	IPACMDBG_H("Free wan clients cache\n");
   4450 
   4451 	/* check software routing fl rule hdl */
   4452 	if (softwarerouting_act == true)
   4453 	{
   4454 		handle_software_routing_disable();
   4455 	}
   4456 
   4457 	/* free filter rule handlers */
   4458 	if (ip_type != IPA_IP_v6 && rx_prop != NULL)
   4459 	{
   4460 		if (m_filtering.DeleteFilteringHdls(dft_v4fl_rule_hdl,
   4461 																				IPA_IP_v4,
   4462 																				IPV4_DEFAULT_FILTERTING_RULES) == false)
   4463 		{
   4464 			IPACMERR("Error Delete Filtering rules, aborting...\n");
   4465 			res = IPACM_FAILURE;
   4466 			goto fail;
   4467 		}
   4468 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES);
   4469 
   4470 		IPACMDBG_H("finished delete default v4 filtering rules\n ");
   4471 	}
   4472 
   4473 
   4474 	if (ip_type != IPA_IP_v4 && rx_prop != NULL)
   4475 	{
   4476 		if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl,
   4477 																				IPA_IP_v6,
   4478 																				IPV6_DEFAULT_FILTERTING_RULES) == false)
   4479 		{
   4480 			IPACMERR("ErrorDeleting Filtering rule, aborting...\n");
   4481 			res = IPACM_FAILURE;
   4482 			goto fail;
   4483 		}
   4484 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES);
   4485 
   4486 		if(num_ipv6_dest_flt_rule > 0 && num_ipv6_dest_flt_rule <= MAX_DEFAULT_v6_ROUTE_RULES)
   4487 		{
   4488 			if(m_filtering.DeleteFilteringHdls(ipv6_dest_flt_rule_hdl,  IPA_IP_v6, num_ipv6_dest_flt_rule) == false)
   4489 			{
   4490 				IPACMERR("Failed to delete ipv6 dest flt rules.\n");
   4491 				res = IPACM_FAILURE;
   4492 				goto fail;
   4493 			}
   4494 			IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, num_ipv6_dest_flt_rule);
   4495 		}
   4496 		IPACMDBG_H("finished delete default v6 filtering rules\n ");
   4497 	}
   4498 	if(hdr_proc_hdl_dummy_v6)
   4499 	{
   4500 		if(m_header.DeleteHeaderProcCtx(hdr_proc_hdl_dummy_v6) == false)
   4501 		{
   4502 			IPACMERR("Failed to delete hdr_proc_hdl_dummy_v6\n");
   4503 			res = IPACM_FAILURE;
   4504 			goto fail;
   4505 		}
   4506 	}
   4507 	if(hdr_hdl_dummy_v6)
   4508 	{
   4509 		if (m_header.DeleteHeaderHdl(hdr_hdl_dummy_v6) == false)
   4510 		{
   4511 			IPACMERR("Failed to delete hdr_hdl_dummy_v6\n");
   4512 			res = IPACM_FAILURE;
   4513 			goto fail;
   4514 		}
   4515 	}
   4516 fail:
   4517 	if (tx_prop != NULL)
   4518 	{
   4519 		free(tx_prop);
   4520 	}
   4521 	if (rx_prop != NULL)
   4522 	{
   4523 		free(rx_prop);
   4524 	}
   4525 	if (iface_query != NULL)
   4526 	{
   4527 		free(iface_query);
   4528 	}
   4529 	if (wan_route_rule_v4_hdl != NULL)
   4530 	{
   4531 		free(wan_route_rule_v4_hdl);
   4532 	}
   4533 	if (wan_route_rule_v6_hdl != NULL)
   4534 	{
   4535 		free(wan_route_rule_v6_hdl);
   4536 	}
   4537 	if (wan_route_rule_v6_hdl_a5 != NULL)
   4538 	{
   4539 		free(wan_route_rule_v6_hdl_a5);
   4540 	}
   4541 	if (wan_client != NULL)
   4542 	{
   4543 		free(wan_client);
   4544 	}
   4545 	close(m_fd_ipa);
   4546 	return res;
   4547 }
   4548 
   4549 int IPACM_Wan::handle_down_evt_ex()
   4550 {
   4551 	int res = IPACM_SUCCESS;
   4552 	uint32_t i, tether_total;
   4553 	int ipa_if_num_tether_tmp[IPA_MAX_IFACE_ENTRIES];
   4554 
   4555 	IPACMDBG_H(" wan handle_down_evt \n");
   4556 
   4557 	/* free ODU filter rule handlers */
   4558 	if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == EMBMS_IF)
   4559 	{
   4560 		embms_is_on = false;
   4561 		/* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */
   4562 		IPACMDBG_H("dev %s add producer dependency\n", dev_name);
   4563 		if (tx_prop != NULL)
   4564 		{
   4565 			IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
   4566 			IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
   4567 		}
   4568 
   4569 		if (rx_prop != NULL)
   4570 		{
   4571 			install_wan_filtering_rule(false);
   4572 			IPACMDBG("finished delete embms filtering rule\n ");
   4573 		}
   4574 		goto fail;
   4575 	}
   4576 
   4577 	/* no iface address up, directly close iface*/
   4578 	if (ip_type == IPACM_IP_NULL)
   4579 	{
   4580 		goto fail;
   4581 	}
   4582 
   4583 	if(ip_type == IPA_IP_v4)
   4584 	{
   4585 		num_ipv4_modem_pdn--;
   4586 		IPACMDBG_H("Now the number of ipv4 modem pdn is %d.\n", num_ipv4_modem_pdn);
   4587 		/* only when default gw goes down we post WAN_DOWN event*/
   4588 		if(is_default_gateway == true)
   4589 		{
   4590 			IPACM_Wan::wan_up = false;
   4591 			del_wan_firewall_rule(IPA_IP_v4);
   4592 			install_wan_filtering_rule(false);
   4593 			handle_route_del_evt_ex(IPA_IP_v4);
   4594 #ifdef FEATURE_IPA_ANDROID
   4595 			/* posting wan_down_tether for all lan clients */
   4596 			for (i=0; i < IPACM_Wan::ipa_if_num_tether_v4_total; i++)
   4597 			{
   4598 				ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v4[i];
   4599 			}
   4600 			tether_total = IPACM_Wan::ipa_if_num_tether_v4_total;
   4601 			for (i=0; i < tether_total; i++)
   4602 			{
   4603 				post_wan_down_tether_evt(IPA_IP_v4, ipa_if_num_tether_tmp[i]);
   4604 				IPACMDBG_H("post_wan_down_tether_v4 iface(%d: %s)\n",
   4605 					i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name);
   4606 			}
   4607 #endif
   4608 			if(IPACM_Wan::wan_up_v6)
   4609 			{
   4610 				IPACMDBG_H("modem v6-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name);
   4611 			}
   4612 			else
   4613 			{
   4614 				memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name));
   4615 			}
   4616 		}
   4617 
   4618 		/* only when the last ipv4 modem interface goes down, delete ipv4 default flt rules*/
   4619 		if(num_ipv4_modem_pdn == 0)
   4620 		{
   4621 			IPACMDBG_H("Now the number of modem ipv4 interface is 0, delete default flt rules.\n");
   4622 		IPACM_Wan::num_v4_flt_rule = 0;
   4623 		memset(IPACM_Wan::flt_rule_v4, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
   4624 		install_wan_filtering_rule(false);
   4625 		}
   4626 
   4627 		if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
   4628 		{
   4629 			IPACMERR("Routing rule deletion failed!\n");
   4630 			res = IPACM_FAILURE;
   4631 			goto fail;
   4632 		}
   4633 	}
   4634 	else if(ip_type == IPA_IP_v6)
   4635 	{
   4636 	    if (num_dft_rt_v6 > 1)
   4637 			num_ipv6_modem_pdn--;
   4638 		IPACMDBG_H("Now the number of ipv6 modem pdn is %d.\n", num_ipv6_modem_pdn);
   4639 		/* only when default gw goes down we post WAN_DOWN event*/
   4640 		if(is_default_gateway == true)
   4641 		{
   4642 			IPACM_Wan::wan_up_v6 = false;
   4643 			del_wan_firewall_rule(IPA_IP_v6);
   4644 			install_wan_filtering_rule(false);
   4645 			handle_route_del_evt_ex(IPA_IP_v6);
   4646 #ifdef FEATURE_IPA_ANDROID
   4647 			/* posting wan_down_tether for all lan clients */
   4648 			for (i=0; i < IPACM_Wan::ipa_if_num_tether_v6_total; i++)
   4649 			{
   4650 				ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v6[i];
   4651 			}
   4652 			tether_total = IPACM_Wan::ipa_if_num_tether_v6_total;
   4653 			for (i=0; i < tether_total; i++)
   4654 			{
   4655 				post_wan_down_tether_evt(IPA_IP_v6, ipa_if_num_tether_tmp[i]);
   4656 				IPACMDBG_H("post_wan_down_tether_v6 iface(%d: %s)\n",
   4657 					i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name);
   4658 			}
   4659 #endif
   4660 			if(IPACM_Wan::wan_up)
   4661 			{
   4662 				IPACMDBG_H("modem v4-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name);
   4663 			}
   4664 			else
   4665 			{
   4666 				memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name));
   4667 			}
   4668 		}
   4669 
   4670 		/* only when the last ipv6 modem interface goes down, delete ipv6 default flt rules*/
   4671 		if(num_ipv6_modem_pdn == 0)
   4672 		{
   4673 			IPACMDBG_H("Now the number of modem ipv6 interface is 0, delete default flt rules.\n");
   4674 		IPACM_Wan::num_v6_flt_rule = 0;
   4675 		memset(IPACM_Wan::flt_rule_v6, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
   4676 		install_wan_filtering_rule(false);
   4677 		}
   4678 
   4679 		for (i = 0; i < 2*num_dft_rt_v6; i++)
   4680 		{
   4681 			if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
   4682 			{
   4683 				IPACMERR("Routing rule deletion failed!\n");
   4684 				res = IPACM_FAILURE;
   4685 				goto fail;
   4686 			}
   4687 		}
   4688 	}
   4689 	else
   4690 	{
   4691 		num_ipv4_modem_pdn--;
   4692 		IPACMDBG_H("Now the number of ipv4 modem pdn is %d.\n", num_ipv4_modem_pdn);
   4693 	    if (num_dft_rt_v6 > 1)
   4694 			num_ipv6_modem_pdn--;
   4695 		IPACMDBG_H("Now the number of ipv6 modem pdn is %d.\n", num_ipv6_modem_pdn);
   4696 		/* only when default gw goes down we post WAN_DOWN event*/
   4697 		if(is_default_gateway == true)
   4698 		{
   4699 			IPACM_Wan::wan_up = false;
   4700 			del_wan_firewall_rule(IPA_IP_v4);
   4701 			handle_route_del_evt_ex(IPA_IP_v4);
   4702 #ifdef FEATURE_IPA_ANDROID
   4703 			/* posting wan_down_tether for all lan clients */
   4704 			for (i=0; i < IPACM_Wan::ipa_if_num_tether_v4_total; i++)
   4705 			{
   4706 				ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v4[i];
   4707 			}
   4708 			tether_total = IPACM_Wan::ipa_if_num_tether_v4_total;
   4709 			for (i=0; i < tether_total; i++)
   4710 			{
   4711 				post_wan_down_tether_evt(IPA_IP_v4, ipa_if_num_tether_tmp[i]);
   4712 				IPACMDBG_H("post_wan_down_tether_v4 iface(%d: %s)\n",
   4713 					i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name);
   4714 			}
   4715 #endif
   4716 			IPACM_Wan::wan_up_v6 = false;
   4717 			del_wan_firewall_rule(IPA_IP_v6);
   4718 			handle_route_del_evt_ex(IPA_IP_v6);
   4719 #ifdef FEATURE_IPA_ANDROID
   4720 			/* posting wan_down_tether for all lan clients */
   4721 			for (i=0; i < IPACM_Wan::ipa_if_num_tether_v6_total; i++)
   4722 			{
   4723 				ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v6[i];
   4724 			}
   4725 			tether_total = IPACM_Wan::ipa_if_num_tether_v6_total;
   4726 			for (i=0; i < tether_total; i++)
   4727 			{
   4728 				post_wan_down_tether_evt(IPA_IP_v6, ipa_if_num_tether_tmp[i]);
   4729 				IPACMDBG_H("post_wan_down_tether_v6 iface(%d: %s)\n",
   4730 					i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name);
   4731 			}
   4732 #endif
   4733 			memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name));
   4734 
   4735 			install_wan_filtering_rule(false);
   4736 		}
   4737 
   4738 		/* only when the last ipv4 modem interface goes down, delete ipv4 default flt rules*/
   4739 		if(num_ipv4_modem_pdn == 0)
   4740 		{
   4741 			IPACMDBG_H("Now the number of modem ipv4 interface is 0, delete default flt rules.\n");
   4742 			IPACM_Wan::num_v4_flt_rule = 0;
   4743 			memset(IPACM_Wan::flt_rule_v4, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
   4744 			install_wan_filtering_rule(false);
   4745 		}
   4746 		/* only when the last ipv6 modem interface goes down, delete ipv6 default flt rules*/
   4747 		if(num_ipv6_modem_pdn == 0)
   4748 		{
   4749 			IPACMDBG_H("Now the number of modem ipv6 interface is 0, delete default flt rules.\n");
   4750 			IPACM_Wan::num_v6_flt_rule = 0;
   4751 			memset(IPACM_Wan::flt_rule_v6, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
   4752 			install_wan_filtering_rule(false);
   4753 		}
   4754 
   4755 		if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
   4756 		{
   4757 			IPACMERR("Routing rule deletion failed!\n");
   4758 			res = IPACM_FAILURE;
   4759 			goto fail;
   4760 		}
   4761 
   4762 		for (i = 0; i < 2*num_dft_rt_v6; i++)
   4763 		{
   4764 			if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
   4765 			{
   4766 				IPACMERR("Routing rule deletion failed!\n");
   4767 				res = IPACM_FAILURE;
   4768 				goto fail;
   4769 			}
   4770 		}
   4771 	}
   4772 
   4773 	/* check software routing fl rule hdl */
   4774 	if (softwarerouting_act == true)
   4775 	{
   4776 		handle_software_routing_disable();
   4777 	}
   4778 
   4779 fail:
   4780 	if (tx_prop != NULL)
   4781 	{
   4782 		free(tx_prop);
   4783 	}
   4784 	if (rx_prop != NULL)
   4785 	{
   4786 		free(rx_prop);
   4787 	}
   4788 	if (ext_prop != NULL)
   4789 	{
   4790 		free(ext_prop);
   4791 	}
   4792 	if (iface_query != NULL)
   4793 	{
   4794 		free(iface_query);
   4795 	}
   4796 	if (wan_route_rule_v4_hdl != NULL)
   4797 	{
   4798 		free(wan_route_rule_v4_hdl);
   4799 	}
   4800 	if (wan_route_rule_v6_hdl != NULL)
   4801 	{
   4802 		free(wan_route_rule_v6_hdl);
   4803 	}
   4804 	if (wan_route_rule_v6_hdl_a5 != NULL)
   4805 	{
   4806 		free(wan_route_rule_v6_hdl_a5);
   4807 	}
   4808 	if (wan_client != NULL)
   4809 	{
   4810 		free(wan_client);
   4811 	}
   4812 	close(m_fd_ipa);
   4813 	return res;
   4814 }
   4815 
   4816 int IPACM_Wan::install_wan_filtering_rule(bool is_sw_routing)
   4817 {
   4818 	int len, res = IPACM_SUCCESS;
   4819 	uint8_t mux_id;
   4820 	ipa_ioc_add_flt_rule *pFilteringTable_v4 = NULL;
   4821 	ipa_ioc_add_flt_rule *pFilteringTable_v6 = NULL;
   4822 
   4823 	mux_id = IPACM_Iface::ipacmcfg->GetQmapId();
   4824 	if(rx_prop == NULL)
   4825 	{
   4826 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
   4827 		return IPACM_SUCCESS;
   4828 	}
   4829 	if (is_sw_routing == true ||
   4830 			IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true)
   4831 	{
   4832 		/* contruct SW-RT rules to Q6*/
   4833 		struct ipa_flt_rule_add flt_rule_entry;
   4834 		struct ipa_ioc_get_rt_tbl_indx rt_tbl_idx;
   4835 		ipa_ioc_generate_flt_eq flt_eq;
   4836 
   4837 		IPACMDBG("\n");
   4838 		if (softwarerouting_act == true)
   4839 		{
   4840 			IPACMDBG("already setup software_routing rule for (%s)iface ip-family %d\n",
   4841 								IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ip_type);
   4842 			return IPACM_SUCCESS;
   4843 		}
   4844 
   4845 		len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add);
   4846 		pFilteringTable_v4 = (struct ipa_ioc_add_flt_rule*)malloc(len);
   4847 		if (pFilteringTable_v4 == NULL)
   4848 		{
   4849 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
   4850 			return IPACM_FAILURE;
   4851 		}
   4852 		memset(pFilteringTable_v4, 0, len);
   4853 		IPACMDBG_H("Total number of WAN DL filtering rule for IPv4 is 1\n");
   4854 
   4855 		pFilteringTable_v4->commit = 1;
   4856 		pFilteringTable_v4->ep = rx_prop->rx[0].src_pipe;
   4857 		pFilteringTable_v4->global = false;
   4858 		pFilteringTable_v4->ip = IPA_IP_v4;
   4859 		pFilteringTable_v4->num_rules = (uint8_t)1;
   4860 
   4861 		/* Configuring Software-Routing Filtering Rule */
   4862 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   4863 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
   4864 		strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
   4865 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   4866 		rt_tbl_idx.ip = IPA_IP_v4;
   4867 		if(ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx) < 0)
   4868 		{
   4869 			IPACMERR("Failed to get routing table index from name\n");
   4870 			res = IPACM_FAILURE;
   4871 			goto fail;
   4872 		}
   4873 		IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
   4874 
   4875 		flt_rule_entry.at_rear = false;
   4876 		flt_rule_entry.flt_rule_hdl = -1;
   4877 		flt_rule_entry.status = -1;
   4878 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   4879 #ifdef FEATURE_IPA_V3
   4880 		flt_rule_entry.rule.hashable = true;
   4881 #endif
   4882 
   4883 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
   4884 
   4885 		memcpy(&flt_rule_entry.rule.attrib,
   4886 					&rx_prop->rx[0].attrib,
   4887 					sizeof(flt_rule_entry.rule.attrib));
   4888 		flt_rule_entry.rule.retain_hdr = 0;
   4889 		flt_rule_entry.rule.to_uc = 0;
   4890 		flt_rule_entry.rule.eq_attrib_type = 1;
   4891 
   4892 		memset(&flt_eq, 0, sizeof(flt_eq));
   4893 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   4894 		flt_eq.ip = IPA_IP_v4;
   4895 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   4896 		{
   4897 			IPACMERR("Failed to get eq_attrib\n");
   4898 			res = IPACM_FAILURE;
   4899 			goto fail;
   4900 		}
   4901 		memcpy(&flt_rule_entry.rule.eq_attrib,
   4902 			&flt_eq.eq_attrib,
   4903 			sizeof(flt_rule_entry.rule.eq_attrib));
   4904 		memcpy(&(pFilteringTable_v4->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   4905 
   4906 		len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add);
   4907 		pFilteringTable_v6 = (struct ipa_ioc_add_flt_rule*)malloc(len);
   4908 		if (pFilteringTable_v6 == NULL)
   4909 		{
   4910 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
   4911 			free(pFilteringTable_v4);
   4912 			return IPACM_FAILURE;
   4913 		}
   4914 		memset(pFilteringTable_v6, 0, len);
   4915 		IPACMDBG_H("Total number of WAN DL filtering rule for IPv6 is 1\n");
   4916 
   4917 		pFilteringTable_v6->commit = 1;
   4918 		pFilteringTable_v6->ep = rx_prop->rx[0].src_pipe;
   4919 		pFilteringTable_v6->global = false;
   4920 		pFilteringTable_v6->ip = IPA_IP_v6;
   4921 		pFilteringTable_v6->num_rules = (uint8_t)1;
   4922 
   4923 		/* Configuring Software-Routing Filtering Rule */
   4924 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   4925 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
   4926 		strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
   4927 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   4928 		rt_tbl_idx.ip = IPA_IP_v6;
   4929 		if(ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx) < 0)
   4930 		{
   4931 			IPACMERR("Failed to get routing table index from name\n");
   4932 			res = IPACM_FAILURE;
   4933 			goto fail;
   4934 		}
   4935 		IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
   4936 
   4937 		flt_rule_entry.at_rear = false;
   4938 		flt_rule_entry.flt_rule_hdl = -1;
   4939 		flt_rule_entry.status = -1;
   4940 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   4941 #ifdef FEATURE_IPA_V3
   4942 		flt_rule_entry.rule.hashable = true;
   4943 #endif
   4944 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
   4945 		memcpy(&flt_rule_entry.rule.attrib,
   4946 					&rx_prop->rx[0].attrib,
   4947 					sizeof(flt_rule_entry.rule.attrib));
   4948 		flt_rule_entry.rule.retain_hdr = 0;
   4949 		flt_rule_entry.rule.to_uc = 0;
   4950 		flt_rule_entry.rule.eq_attrib_type = 1;
   4951 
   4952 		memset(&flt_eq, 0, sizeof(flt_eq));
   4953 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
   4954 		flt_eq.ip = IPA_IP_v6;
   4955 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
   4956 		{
   4957 			IPACMERR("Failed to get eq_attrib\n");
   4958 			res = IPACM_FAILURE;
   4959 			goto fail;
   4960 		}
   4961 		memcpy(&flt_rule_entry.rule.eq_attrib,
   4962 			&flt_eq.eq_attrib,
   4963 			sizeof(flt_rule_entry.rule.eq_attrib));
   4964 		memcpy(&(pFilteringTable_v6->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   4965 		softwarerouting_act = true;
   4966 		/* end of contruct SW-RT rules to Q6*/
   4967 	}
   4968 	else
   4969 	{
   4970 		if(embms_is_on == false)
   4971 		{
   4972 			if(IPACM_Wan::num_v4_flt_rule > 0)
   4973 			{
   4974 				len = sizeof(struct ipa_ioc_add_flt_rule) + IPACM_Wan::num_v4_flt_rule * sizeof(struct ipa_flt_rule_add);
   4975 				pFilteringTable_v4 = (struct ipa_ioc_add_flt_rule*)malloc(len);
   4976 
   4977 				IPACMDBG_H("Total number of WAN DL filtering rule for IPv4 is %d\n", IPACM_Wan::num_v4_flt_rule);
   4978 
   4979 				if (pFilteringTable_v4 == NULL)
   4980 				{
   4981 					IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
   4982 					return IPACM_FAILURE;
   4983 				}
   4984 				memset(pFilteringTable_v4, 0, len);
   4985 				pFilteringTable_v4->commit = 1;
   4986 				pFilteringTable_v4->ep = rx_prop->rx[0].src_pipe;
   4987 				pFilteringTable_v4->global = false;
   4988 				pFilteringTable_v4->ip = IPA_IP_v4;
   4989 				pFilteringTable_v4->num_rules = (uint8_t)IPACM_Wan::num_v4_flt_rule;
   4990 
   4991 				memcpy(pFilteringTable_v4->rules, IPACM_Wan::flt_rule_v4, IPACM_Wan::num_v4_flt_rule * sizeof(ipa_flt_rule_add));
   4992 			}
   4993 
   4994 			if(IPACM_Wan::num_v6_flt_rule > 0)
   4995 			{
   4996 				len = sizeof(struct ipa_ioc_add_flt_rule) + IPACM_Wan::num_v6_flt_rule * sizeof(struct ipa_flt_rule_add);
   4997 				pFilteringTable_v6 = (struct ipa_ioc_add_flt_rule*)malloc(len);
   4998 
   4999 				IPACMDBG_H("Total number of WAN DL filtering rule for IPv6 is %d\n", IPACM_Wan::num_v6_flt_rule);
   5000 
   5001 				if (pFilteringTable_v6 == NULL)
   5002 				{
   5003 					IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
   5004 					free(pFilteringTable_v4);
   5005 					return IPACM_FAILURE;
   5006 				}
   5007 				memset(pFilteringTable_v6, 0, len);
   5008 				pFilteringTable_v6->commit = 1;
   5009 				pFilteringTable_v6->ep = rx_prop->rx[0].src_pipe;
   5010 				pFilteringTable_v6->global = false;
   5011 				pFilteringTable_v6->ip = IPA_IP_v6;
   5012 				pFilteringTable_v6->num_rules = (uint8_t)IPACM_Wan::num_v6_flt_rule;
   5013 
   5014 				memcpy(pFilteringTable_v6->rules, IPACM_Wan::flt_rule_v6, IPACM_Wan::num_v6_flt_rule * sizeof(ipa_flt_rule_add));
   5015 			}
   5016 		}
   5017 		else	//embms is on, always add 1 embms rule on top of WAN DL flt table
   5018 		{
   5019 			/* allocate ipv4 filtering table */
   5020 			len = sizeof(struct ipa_ioc_add_flt_rule) + (1 + IPACM_Wan::num_v4_flt_rule) * sizeof(struct ipa_flt_rule_add);
   5021 			pFilteringTable_v4 = (struct ipa_ioc_add_flt_rule*)malloc(len);
   5022 			IPACMDBG_H("Total number of WAN DL filtering rule for IPv4 is %d\n", IPACM_Wan::num_v4_flt_rule + 1);
   5023 			if (pFilteringTable_v4 == NULL)
   5024 			{
   5025 				IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
   5026 				return IPACM_FAILURE;
   5027 			}
   5028 			memset(pFilteringTable_v4, 0, len);
   5029 			pFilteringTable_v4->commit = 1;
   5030 			pFilteringTable_v4->ep = rx_prop->rx[0].src_pipe;
   5031 			pFilteringTable_v4->global = false;
   5032 			pFilteringTable_v4->ip = IPA_IP_v4;
   5033 			pFilteringTable_v4->num_rules = (uint8_t)IPACM_Wan::num_v4_flt_rule + 1;
   5034 
   5035 			/* allocate ipv6 filtering table */
   5036 			len = sizeof(struct ipa_ioc_add_flt_rule) + (1 + IPACM_Wan::num_v6_flt_rule) * sizeof(struct ipa_flt_rule_add);
   5037 			pFilteringTable_v6 = (struct ipa_ioc_add_flt_rule*)malloc(len);
   5038 			IPACMDBG_H("Total number of WAN DL filtering rule for IPv6 is %d\n", IPACM_Wan::num_v6_flt_rule + 1);
   5039 			if (pFilteringTable_v6 == NULL)
   5040 			{
   5041 				IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
   5042 				free(pFilteringTable_v4);
   5043 				return IPACM_FAILURE;
   5044 			}
   5045 			memset(pFilteringTable_v6, 0, len);
   5046 			pFilteringTable_v6->commit = 1;
   5047 			pFilteringTable_v6->ep = rx_prop->rx[0].src_pipe;
   5048 			pFilteringTable_v6->global = false;
   5049 			pFilteringTable_v6->ip = IPA_IP_v6;
   5050 			pFilteringTable_v6->num_rules = (uint8_t)IPACM_Wan::num_v6_flt_rule + 1;
   5051 
   5052 			config_dft_embms_rules(pFilteringTable_v4, pFilteringTable_v6);
   5053 			if(IPACM_Wan::num_v4_flt_rule > 0)
   5054 			{
   5055 				memcpy(&(pFilteringTable_v4->rules[1]), IPACM_Wan::flt_rule_v4, IPACM_Wan::num_v4_flt_rule * sizeof(ipa_flt_rule_add));
   5056 			}
   5057 
   5058 			if(IPACM_Wan::num_v6_flt_rule > 0)
   5059 			{
   5060 				memcpy(&(pFilteringTable_v6->rules[1]), IPACM_Wan::flt_rule_v6, IPACM_Wan::num_v6_flt_rule * sizeof(ipa_flt_rule_add));
   5061 			}
   5062 		}
   5063 	}
   5064 
   5065 	if(false == m_filtering.AddWanDLFilteringRule(pFilteringTable_v4, pFilteringTable_v6, mux_id))
   5066 	{
   5067 		IPACMERR("Failed to install WAN DL filtering table.\n");
   5068 		res = IPACM_FAILURE;
   5069 		goto fail;
   5070 	}
   5071 
   5072 fail:
   5073 	if(pFilteringTable_v4 != NULL)
   5074 	{
   5075 		free(pFilteringTable_v4);
   5076 	}
   5077 	if(pFilteringTable_v6 != NULL)
   5078 	{
   5079 		free(pFilteringTable_v6);
   5080 	}
   5081 	return res;
   5082 }
   5083 
   5084 void IPACM_Wan::change_to_network_order(ipa_ip_type iptype, ipa_rule_attrib* attrib)
   5085 {
   5086 	if(attrib == NULL)
   5087 	{
   5088 		IPACMERR("Attribute pointer is NULL.\n");
   5089 		return;
   5090 	}
   5091 
   5092 	if(iptype == IPA_IP_v6)
   5093 	{
   5094 		int i;
   5095 		for(i=0; i<4; i++)
   5096 		{
   5097 			attrib->u.v6.src_addr[i] = htonl(attrib->u.v6.src_addr[i]);
   5098 			attrib->u.v6.src_addr_mask[i] = htonl(attrib->u.v6.src_addr_mask[i]);
   5099 			attrib->u.v6.dst_addr[i] = htonl(attrib->u.v6.dst_addr[i]);
   5100 			attrib->u.v6.dst_addr_mask[i] = htonl(attrib->u.v6.dst_addr_mask[i]);
   5101 		}
   5102 	}
   5103 	else
   5104 	{
   5105 		IPACMDBG_H("IP type is not IPv6, do nothing: %d\n", iptype);
   5106 	}
   5107 
   5108 	return;
   5109 }
   5110 
   5111 bool IPACM_Wan::is_global_ipv6_addr(uint32_t* ipv6_addr)
   5112 {
   5113 	if(ipv6_addr == NULL)
   5114 	{
   5115 		IPACMERR("IPv6 address is empty.\n");
   5116 		return false;
   5117 	}
   5118 	IPACMDBG_H("Get ipv6 address with first word 0x%08x.\n", ipv6_addr[0]);
   5119 
   5120 	uint32_t ipv6_link_local_prefix, ipv6_link_local_prefix_mask;
   5121 	ipv6_link_local_prefix = 0xFE800000;
   5122 	ipv6_link_local_prefix_mask = 0xFFC00000;
   5123 	if((ipv6_addr[0] & ipv6_link_local_prefix_mask) == (ipv6_link_local_prefix & ipv6_link_local_prefix_mask))
   5124 	{
   5125 		IPACMDBG_H("This IPv6 address is link local.\n");
   5126 		return false;
   5127 	}
   5128 	else
   5129 	{
   5130 		IPACMDBG_H("This IPv6 address is not link local.\n");
   5131 		return true;
   5132 	}
   5133 }
   5134 
   5135 /* handle STA WAN-client */
   5136 /* handle WAN client initial, construct full headers (tx property) */
   5137 int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr)
   5138 {
   5139 
   5140 #define WAN_IFACE_INDEX_LEN 2
   5141 
   5142 	int res = IPACM_SUCCESS, len = 0;
   5143 	char index[WAN_IFACE_INDEX_LEN];
   5144 	struct ipa_ioc_copy_hdr sCopyHeader;
   5145 	struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL;
   5146 	uint32_t cnt;
   5147 	int clnt_indx;
   5148 
   5149 	clnt_indx = get_wan_client_index(mac_addr);
   5150 
   5151 	if (clnt_indx != IPACM_INVALID_INDEX)
   5152 	{
   5153 		IPACMERR("eth client is found/attached already with index %d \n", clnt_indx);
   5154 		return IPACM_FAILURE;
   5155 	}
   5156 
   5157 	/* add header to IPA */
   5158 	if (num_wan_client >= IPA_MAX_NUM_WAN_CLIENTS)
   5159 	{
   5160 		IPACMERR("Reached maximum number(%d) of eth clients\n", IPA_MAX_NUM_WAN_CLIENTS);
   5161 		return IPACM_FAILURE;
   5162 	}
   5163 
   5164 	IPACMDBG_H("WAN client number: %d\n", num_wan_client);
   5165 
   5166 	memcpy(get_client_memptr(wan_client, num_wan_client)->mac,
   5167 				 mac_addr,
   5168 				 sizeof(get_client_memptr(wan_client, num_wan_client)->mac));
   5169 
   5170 	IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
   5171 					 mac_addr[0], mac_addr[1], mac_addr[2],
   5172 					 mac_addr[3], mac_addr[4], mac_addr[5]);
   5173 
   5174 	IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
   5175 					 get_client_memptr(wan_client, num_wan_client)->mac[0],
   5176 					 get_client_memptr(wan_client, num_wan_client)->mac[1],
   5177 					 get_client_memptr(wan_client, num_wan_client)->mac[2],
   5178 					 get_client_memptr(wan_client, num_wan_client)->mac[3],
   5179 					 get_client_memptr(wan_client, num_wan_client)->mac[4],
   5180 					 get_client_memptr(wan_client, num_wan_client)->mac[5]);
   5181 
   5182 	/* add header to IPA */
   5183 	if(tx_prop != NULL)
   5184 	{
   5185 		len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add));
   5186 		pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len);
   5187 		if (pHeaderDescriptor == NULL)
   5188 		{
   5189 			IPACMERR("calloc failed to allocate pHeaderDescriptor\n");
   5190 			return IPACM_FAILURE;
   5191 		}
   5192 
   5193 		/* copy partial header for v4*/
   5194 		for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
   5195 		{
   5196 				 if(tx_prop->tx[cnt].ip==IPA_IP_v4)
   5197 				 {
   5198 								IPACMDBG_H("Got partial v4-header name from %d tx props\n", cnt);
   5199 								memset(&sCopyHeader, 0, sizeof(sCopyHeader));
   5200 								memcpy(sCopyHeader.name,
   5201 											 tx_prop->tx[cnt].hdr_name,
   5202 											 sizeof(sCopyHeader.name));
   5203 
   5204 								IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt);
   5205 								if (m_header.CopyHeader(&sCopyHeader) == false)
   5206 								{
   5207 									PERROR("ioctl copy header failed");
   5208 									res = IPACM_FAILURE;
   5209 									goto fail;
   5210 								}
   5211 
   5212 								IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
   5213 								IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst);
   5214 								if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE)
   5215 								{
   5216 									IPACMERR("header oversize\n");
   5217 									res = IPACM_FAILURE;
   5218 									goto fail;
   5219 								}
   5220 								else
   5221 								{
   5222 									memcpy(pHeaderDescriptor->hdr[0].hdr,
   5223 												 sCopyHeader.hdr,
   5224 												 sCopyHeader.hdr_len);
   5225 								}
   5226 
   5227 								/* copy client mac_addr to partial header */
   5228 								IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n",
   5229 										sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst);
   5230 
   5231 								/* only copy 6 bytes mac-address */
   5232 								if(sCopyHeader.is_eth2_ofst_valid == false)
   5233 								{
   5234 									memcpy(&pHeaderDescriptor->hdr[0].hdr[0],
   5235 											mac_addr, IPA_MAC_ADDR_SIZE);
   5236 								}
   5237 								else
   5238 								{
   5239 									memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst],
   5240 											mac_addr, IPA_MAC_ADDR_SIZE);
   5241 								}
   5242 
   5243 
   5244 								pHeaderDescriptor->commit = true;
   5245 								pHeaderDescriptor->num_hdrs = 1;
   5246 
   5247 								memset(pHeaderDescriptor->hdr[0].name, 0,
   5248 											 sizeof(pHeaderDescriptor->hdr[0].name));
   5249 
   5250 								snprintf(index,sizeof(index), "%d", ipa_if_num);
   5251 								strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name));
   5252 								pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   5253 								if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_WAN_PARTIAL_HDR_NAME_v4, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX)
   5254 								{
   5255 									IPACMERR(" header name construction failed exceed length (%zu)\n", strlen(pHeaderDescriptor->hdr[0].name));
   5256 									res = IPACM_FAILURE;
   5257 									goto fail;
   5258 								}
   5259 
   5260 								snprintf(index,sizeof(index), "%d", header_name_count);
   5261 								if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX)
   5262 								{
   5263 									IPACMERR(" header name construction failed exceed length (%zu)\n", strlen(pHeaderDescriptor->hdr[0].name));
   5264 									res = IPACM_FAILURE;
   5265 									goto fail;
   5266 								}
   5267 
   5268 								pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len;
   5269 								pHeaderDescriptor->hdr[0].hdr_hdl = -1;
   5270 								pHeaderDescriptor->hdr[0].is_partial = 0;
   5271 								pHeaderDescriptor->hdr[0].status = -1;
   5272 
   5273 					 if (m_header.AddHeader(pHeaderDescriptor) == false ||
   5274 							pHeaderDescriptor->hdr[0].status != 0)
   5275 					 {
   5276 						IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status);
   5277 						res = IPACM_FAILURE;
   5278 						goto fail;
   5279 					 }
   5280 
   5281 					get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl;
   5282 					IPACMDBG_H("eth-client(%d) v4 full header name:%s header handle:(0x%x)\n",
   5283 												 num_wan_client,
   5284 												 pHeaderDescriptor->hdr[0].name,
   5285 												 get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v4);
   5286 									get_client_memptr(wan_client, num_wan_client)->ipv4_header_set=true;
   5287 
   5288 					break;
   5289 				 }
   5290 		}
   5291 
   5292 
   5293 		/* copy partial header for v6*/
   5294 		for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
   5295 		{
   5296 			if(tx_prop->tx[cnt].ip==IPA_IP_v6)
   5297 			{
   5298 
   5299 				IPACMDBG_H("Got partial v6-header name from %d tx props\n", cnt);
   5300 				memset(&sCopyHeader, 0, sizeof(sCopyHeader));
   5301 				memcpy(sCopyHeader.name,
   5302 						tx_prop->tx[cnt].hdr_name,
   5303 							sizeof(sCopyHeader.name));
   5304 
   5305 				IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt);
   5306 				if (m_header.CopyHeader(&sCopyHeader) == false)
   5307 				{
   5308 					PERROR("ioctl copy header failed");
   5309 					res = IPACM_FAILURE;
   5310 					goto fail;
   5311 				}
   5312 
   5313 				IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
   5314 				IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst);
   5315 				if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE)
   5316 				{
   5317 					IPACMERR("header oversize\n");
   5318 					res = IPACM_FAILURE;
   5319 					goto fail;
   5320 				}
   5321 				else
   5322 				{
   5323 					memcpy(pHeaderDescriptor->hdr[0].hdr,
   5324 							sCopyHeader.hdr,
   5325 							sCopyHeader.hdr_len);
   5326 				}
   5327 
   5328 				/* copy client mac_addr to partial header */
   5329 				if(sCopyHeader.is_eth2_ofst_valid == false)
   5330 				{
   5331 					memcpy(&pHeaderDescriptor->hdr[0].hdr[0],
   5332 								 mac_addr, IPA_MAC_ADDR_SIZE); /* only copy 6 bytes mac-address */
   5333 				}
   5334 				else
   5335 				{
   5336 					memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst],
   5337 								 mac_addr, IPA_MAC_ADDR_SIZE); /* only copy 6 bytes mac-address */
   5338 				}
   5339 
   5340 
   5341 				pHeaderDescriptor->commit = true;
   5342 				pHeaderDescriptor->num_hdrs = 1;
   5343 
   5344 				memset(pHeaderDescriptor->hdr[0].name, 0,
   5345 					 sizeof(pHeaderDescriptor->hdr[0].name));
   5346 
   5347 				snprintf(index,sizeof(index), "%d", ipa_if_num);
   5348 				strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name));
   5349 				pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   5350 				if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_WAN_PARTIAL_HDR_NAME_v6, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX)
   5351 				{
   5352 					IPACMERR(" header name construction failed exceed length (%zu)\n", strlen(pHeaderDescriptor->hdr[0].name));
   5353 					res = IPACM_FAILURE;
   5354 					goto fail;
   5355 				}
   5356 				snprintf(index,sizeof(index), "%d", header_name_count);
   5357 				if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX)
   5358 				{
   5359 					IPACMERR(" header name construction failed exceed length (%zu)\n", strlen(pHeaderDescriptor->hdr[0].name));
   5360 					res = IPACM_FAILURE;
   5361 					goto fail;
   5362 				}
   5363 
   5364 				pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len;
   5365 				pHeaderDescriptor->hdr[0].hdr_hdl = -1;
   5366 				pHeaderDescriptor->hdr[0].is_partial = 0;
   5367 				pHeaderDescriptor->hdr[0].status = -1;
   5368 
   5369 				if (m_header.AddHeader(pHeaderDescriptor) == false ||
   5370 						pHeaderDescriptor->hdr[0].status != 0)
   5371 				{
   5372 					IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status);
   5373 					res = IPACM_FAILURE;
   5374 					goto fail;
   5375 				}
   5376 
   5377 				get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl;
   5378 				IPACMDBG_H("eth-client(%d) v6 full header name:%s header handle:(0x%x)\n",
   5379 						 num_wan_client,
   5380 						 pHeaderDescriptor->hdr[0].name,
   5381 									 get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v6);
   5382 
   5383 									get_client_memptr(wan_client, num_wan_client)->ipv6_header_set=true;
   5384 
   5385 				break;
   5386 
   5387 			}
   5388 		}
   5389 		/* initialize wifi client*/
   5390 		get_client_memptr(wan_client, num_wan_client)->route_rule_set_v4 = false;
   5391 		get_client_memptr(wan_client, num_wan_client)->route_rule_set_v6 = 0;
   5392 		get_client_memptr(wan_client, num_wan_client)->ipv4_set = false;
   5393 		get_client_memptr(wan_client, num_wan_client)->ipv6_set = 0;
   5394 		num_wan_client++;
   5395 		header_name_count++; //keep increasing header_name_count
   5396 		res = IPACM_SUCCESS;
   5397 		IPACMDBG_H("eth client number: %d\n", num_wan_client);
   5398 	}
   5399 	else
   5400 	{
   5401 		return res;
   5402 	}
   5403 fail:
   5404 	free(pHeaderDescriptor);
   5405 
   5406 	return res;
   5407 }
   5408 
   5409 /*handle eth client */
   5410 int IPACM_Wan::handle_wan_client_ipaddr(ipacm_event_data_all *data)
   5411 {
   5412 	int clnt_indx;
   5413 	int v6_num;
   5414 
   5415 	IPACMDBG_H("number of wan clients: %d\n", num_wan_client);
   5416 	IPACMDBG_H(" event MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
   5417 					 data->mac_addr[0],
   5418 					 data->mac_addr[1],
   5419 					 data->mac_addr[2],
   5420 					 data->mac_addr[3],
   5421 					 data->mac_addr[4],
   5422 					 data->mac_addr[5]);
   5423 
   5424 	clnt_indx = get_wan_client_index(data->mac_addr);
   5425 
   5426 		if (clnt_indx == IPACM_INVALID_INDEX)
   5427 		{
   5428 			IPACMERR("wan client not found/attached \n");
   5429 			return IPACM_FAILURE;
   5430 		}
   5431 
   5432 	IPACMDBG_H("Ip-type received %d\n", data->iptype);
   5433 	if (data->iptype == IPA_IP_v4)
   5434 	{
   5435 		IPACMDBG_H("ipv4 address: 0x%x\n", data->ipv4_addr);
   5436 		if (data->ipv4_addr != 0) /* not 0.0.0.0 */
   5437 		{
   5438 			if (get_client_memptr(wan_client, clnt_indx)->ipv4_set == false)
   5439 			{
   5440 				get_client_memptr(wan_client, clnt_indx)->v4_addr = data->ipv4_addr;
   5441 				get_client_memptr(wan_client, clnt_indx)->ipv4_set = true;
   5442 				/* Add NAT rules after ipv4 RT rules are set */
   5443 				CtList->HandleSTAClientAddEvt(data->ipv4_addr);
   5444 			}
   5445 			else
   5446 			{
   5447 			   /* check if client got new IPv4 address*/
   5448 			   if(data->ipv4_addr == get_client_memptr(wan_client, clnt_indx)->v4_addr)
   5449 			   {
   5450 			     IPACMDBG_H("Already setup ipv4 addr for client:%d, ipv4 address didn't change\n", clnt_indx);
   5451 				 return IPACM_FAILURE;
   5452 			   }
   5453 			   else
   5454 			   {
   5455 					IPACMDBG_H("ipv4 addr for client:%d is changed \n", clnt_indx);
   5456 					/* Del NAT rules before ipv4 RT rules are delete */
   5457 					CtList->HandleSTAClientDelEvt(get_client_memptr(wan_client, clnt_indx)->v4_addr);
   5458 					delete_wan_rtrules(clnt_indx,IPA_IP_v4);
   5459 					get_client_memptr(wan_client, clnt_indx)->route_rule_set_v4 = false;
   5460 					get_client_memptr(wan_client, clnt_indx)->v4_addr = data->ipv4_addr;
   5461 					/* Add NAT rules after ipv4 RT rules are set */
   5462 					CtList->HandleSTAClientAddEvt(data->ipv4_addr);
   5463 				}
   5464 			}
   5465 		}
   5466 		else
   5467 		{
   5468 				IPACMDBG_H("Invalid client IPv4 address \n");
   5469 				return IPACM_FAILURE;
   5470 		}
   5471 	}
   5472 	else
   5473 	{
   5474 		if ((data->ipv6_addr[0] != 0) || (data->ipv6_addr[1] != 0) ||
   5475 				(data->ipv6_addr[2] != 0) || (data->ipv6_addr[3] != 0)) /* check if all 0 not valid ipv6 address */
   5476 		{
   5477 		   IPACMDBG_H("ipv6 address: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]);
   5478                    if(get_client_memptr(wan_client, clnt_indx)->ipv6_set < IPV6_NUM_ADDR)
   5479 		   {
   5480 
   5481 		       for(v6_num=0;v6_num < get_client_memptr(wan_client, clnt_indx)->ipv6_set;v6_num++)
   5482 	               {
   5483 			      if( data->ipv6_addr[0] == get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][0] &&
   5484 			           data->ipv6_addr[1] == get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][1] &&
   5485 			  	        data->ipv6_addr[2]== get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][2] &&
   5486 			  	         data->ipv6_addr[3] == get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][3])
   5487 			      {
   5488 			  	    IPACMDBG_H("Already see this ipv6 addr for client:%d\n", clnt_indx);
   5489 			  	    return IPACM_FAILURE; /* not setup the RT rules*/
   5490 			      }
   5491 		       }
   5492 
   5493 		       /* not see this ipv6 before for wifi client*/
   5494 			   get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][0] = data->ipv6_addr[0];
   5495 			   get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][1] = data->ipv6_addr[1];
   5496 			   get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][2] = data->ipv6_addr[2];
   5497 			   get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][3] = data->ipv6_addr[3];
   5498 			   get_client_memptr(wan_client, clnt_indx)->ipv6_set++;
   5499 		    }
   5500 		    else
   5501 		    {
   5502 		         IPACMDBG_H("Already got 3 ipv6 addr for client:%d\n", clnt_indx);
   5503 			 return IPACM_FAILURE; /* not setup the RT rules*/
   5504 		    }
   5505 		}
   5506 		else
   5507 		{
   5508 			IPACMDBG_H("Invalid IPV6 address\n");
   5509 			return IPACM_FAILURE;
   5510 		}
   5511 	}
   5512 
   5513 	return IPACM_SUCCESS;
   5514 }
   5515 
   5516 /*handle wan client routing rule*/
   5517 int IPACM_Wan::handle_wan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype)
   5518 {
   5519 	struct ipa_ioc_add_rt_rule *rt_rule;
   5520 	struct ipa_rt_rule_add *rt_rule_entry;
   5521 	uint32_t tx_index;
   5522 	int wan_index,v6_num;
   5523 	const int NUM = 1;
   5524 
   5525 	if(tx_prop == NULL)
   5526 	{
   5527 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
   5528 		return IPACM_SUCCESS;
   5529 	}
   5530 
   5531 	IPACMDBG_H("Received mac_addr MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
   5532 			mac_addr[0], mac_addr[1], mac_addr[2],
   5533 			mac_addr[3], mac_addr[4], mac_addr[5]);
   5534 
   5535 	wan_index = get_wan_client_index(mac_addr);
   5536 	if (wan_index == IPACM_INVALID_INDEX)
   5537 	{
   5538 		IPACMDBG_H("wan client not found/attached \n");
   5539 		return IPACM_SUCCESS;
   5540 	}
   5541 
   5542 	if (iptype==IPA_IP_v4) {
   5543 		IPACMDBG_H("wan client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", wan_index, iptype,
   5544 				get_client_memptr(wan_client, wan_index)->ipv4_set,
   5545 				get_client_memptr(wan_client, wan_index)->route_rule_set_v4);
   5546 	} else {
   5547 		IPACMDBG_H("wan client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", wan_index, iptype,
   5548 				get_client_memptr(wan_client, wan_index)->ipv6_set,
   5549 				get_client_memptr(wan_client, wan_index)->route_rule_set_v6);
   5550 	}
   5551 
   5552 	/* Add default routing rules if not set yet */
   5553 	if ((iptype == IPA_IP_v4
   5554 				&& get_client_memptr(wan_client, wan_index)->route_rule_set_v4 == false
   5555 				&& get_client_memptr(wan_client, wan_index)->ipv4_set == true)
   5556 			|| (iptype == IPA_IP_v6
   5557 				&& get_client_memptr(wan_client, wan_index)->route_rule_set_v6 < get_client_memptr(wan_client, wan_index)->ipv6_set
   5558 			   ))
   5559 	{
   5560 
   5561 		/* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */
   5562 		IPACMDBG_H("dev %s add producer dependency\n", dev_name);
   5563 		IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
   5564 		IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false);
   5565 
   5566 		rt_rule = (struct ipa_ioc_add_rt_rule *)
   5567 			calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
   5568 					NUM * sizeof(struct ipa_rt_rule_add));
   5569 
   5570 		if (rt_rule == NULL)
   5571 		{
   5572 			PERROR("Error Locate ipa_ioc_add_rt_rule memory...\n");
   5573 			return IPACM_FAILURE;
   5574 		}
   5575 
   5576 		rt_rule->commit = 1;
   5577 		rt_rule->num_rules = (uint8_t)NUM;
   5578 		rt_rule->ip = iptype;
   5579 
   5580 		for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
   5581 		{
   5582 			if(iptype != tx_prop->tx[tx_index].ip)
   5583 			{
   5584 				IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n",
   5585 						tx_index, tx_prop->tx[tx_index].ip,iptype);
   5586 				continue;
   5587 			}
   5588 
   5589 			rt_rule_entry = &rt_rule->rules[0];
   5590 			rt_rule_entry->at_rear = 0;
   5591 
   5592 			if (iptype == IPA_IP_v4)
   5593 			{
   5594 				IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", wan_index,
   5595 						get_client_memptr(wan_client, wan_index)->v4_addr);
   5596 
   5597 				IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n",
   5598 						wan_index,
   5599 						get_client_memptr(wan_client, wan_index)->hdr_hdl_v4);
   5600 				strlcpy(rt_rule->rt_tbl_name,
   5601 						IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name,
   5602 						sizeof(rt_rule->rt_tbl_name));
   5603 				rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   5604 				if (IPACM_Iface::ipacmcfg->isMCC_Mode == true)
   5605 				{
   5606 					IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
   5607 							tx_prop->tx[tx_index].alt_dst_pipe);
   5608 					rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
   5609 				}
   5610 				else
   5611 				{
   5612 					rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
   5613 				}
   5614 				memcpy(&rt_rule_entry->rule.attrib,
   5615 						&tx_prop->tx[tx_index].attrib,
   5616 						sizeof(rt_rule_entry->rule.attrib));
   5617 				rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   5618 				rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, wan_index)->hdr_hdl_v4;
   5619 				rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wan_client, wan_index)->v4_addr;
   5620 				rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
   5621 #ifdef FEATURE_IPA_V3
   5622 				rt_rule_entry->rule.hashable = true;
   5623 #endif
   5624 				if (false == m_routing.AddRoutingRule(rt_rule))
   5625 				{
   5626 					IPACMERR("Routing rule addition failed!\n");
   5627 					free(rt_rule);
   5628 					return IPACM_FAILURE;
   5629 				}
   5630 
   5631 				/* copy ipv4 RT hdl */
   5632 				get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4 =
   5633 					rt_rule->rules[0].rt_rule_hdl;
   5634 				IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index,
   5635 						get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4, iptype);
   5636 			} else {
   5637 
   5638 				for(v6_num = get_client_memptr(wan_client, wan_index)->route_rule_set_v6;v6_num < get_client_memptr(wan_client, wan_index)->ipv6_set;v6_num++)
   5639 				{
   5640 					IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n",
   5641 							wan_index,
   5642 							get_client_memptr(wan_client, wan_index)->hdr_hdl_v6);
   5643 
   5644 					/* v6 LAN_RT_TBL */
   5645 					strlcpy(rt_rule->rt_tbl_name,
   5646 							IPACM_Iface::ipacmcfg->rt_tbl_v6.name,
   5647 							sizeof(rt_rule->rt_tbl_name));
   5648 					rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   5649 					/* Uplink going to wan clients should go to IPA */
   5650 					if (IPACM_Iface::ipacmcfg->isMCC_Mode == true)
   5651 					{
   5652 						IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
   5653 								tx_prop->tx[tx_index].alt_dst_pipe);
   5654 						rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
   5655 					}
   5656 					else
   5657 					{
   5658 						rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
   5659 					}
   5660 					memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib));
   5661 					rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, wan_index)->hdr_hdl_v6;;
   5662 					rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   5663 					rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][0];
   5664 					rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][1];
   5665 					rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][2];
   5666 					rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][3];
   5667 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
   5668 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
   5669 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
   5670 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
   5671 #ifdef FEATURE_IPA_V3
   5672 					rt_rule_entry->rule.hashable = true;
   5673 #endif
   5674 					if (false == m_routing.AddRoutingRule(rt_rule))
   5675 					{
   5676 						IPACMERR("Routing rule addition failed!\n");
   5677 						free(rt_rule);
   5678 						return IPACM_FAILURE;
   5679 					}
   5680 
   5681 					get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6[v6_num] = rt_rule->rules[0].rt_rule_hdl;
   5682 					IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index,
   5683 							get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6[v6_num], iptype);
   5684 
   5685 					/*Copy same rule to v6 WAN RT TBL*/
   5686 					strlcpy(rt_rule->rt_tbl_name,
   5687 							IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name,
   5688 							sizeof(rt_rule->rt_tbl_name));
   5689 					rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   5690 					/* Downlink traffic from Wan clients, should go exception */
   5691 					rt_rule_entry->rule.dst = iface_query->excp_pipe;
   5692 					memcpy(&rt_rule_entry->rule.attrib,
   5693 							&tx_prop->tx[tx_index].attrib,
   5694 							sizeof(rt_rule_entry->rule.attrib));
   5695 					rt_rule_entry->rule.hdr_hdl = 0;
   5696 					rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   5697 					rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][0];
   5698 					rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][1];
   5699 					rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][2];
   5700 					rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][3];
   5701 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
   5702 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
   5703 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
   5704 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
   5705 					if (false == m_routing.AddRoutingRule(rt_rule))
   5706 					{
   5707 						IPACMERR("Routing rule addition failed!\n");
   5708 						free(rt_rule);
   5709 						return IPACM_FAILURE;
   5710 					}
   5711 
   5712 					get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num] = rt_rule->rules[0].rt_rule_hdl;
   5713 					IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index,
   5714 							get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num], iptype);
   5715 				}
   5716 			}
   5717 
   5718 		} /* end of for loop */
   5719 
   5720 		free(rt_rule);
   5721 
   5722 		if (iptype == IPA_IP_v4)
   5723 		{
   5724 			get_client_memptr(wan_client, wan_index)->route_rule_set_v4 = true;
   5725 		}
   5726 		else
   5727 		{
   5728 			get_client_memptr(wan_client, wan_index)->route_rule_set_v6 = get_client_memptr(wan_client, wan_index)->ipv6_set;
   5729 		}
   5730 	}
   5731 
   5732 	return IPACM_SUCCESS;
   5733 }
   5734 
   5735 /* TODO Handle wan client routing rules also */
   5736 void IPACM_Wan::handle_wlan_SCC_MCC_switch(bool isSCCMode, ipa_ip_type iptype)
   5737 {
   5738 	struct ipa_ioc_mdfy_rt_rule *rt_rule = NULL;
   5739 	struct ipa_rt_rule_mdfy *rt_rule_entry;
   5740 	uint32_t tx_index = 0;
   5741 
   5742 	IPACMDBG("\n");
   5743 	if (tx_prop == NULL || is_default_gateway == false)
   5744 	{
   5745 		IPACMDBG_H("No tx properties or no default route set yet\n");
   5746 		return;
   5747 	}
   5748 
   5749 	const int NUM = tx_prop->num_tx_props;
   5750 
   5751 	for (tx_index = 0; tx_index < tx_prop->num_tx_props; tx_index++)
   5752 	{
   5753 		if (tx_prop->tx[tx_index].ip != iptype)
   5754 		{
   5755 			IPACMDBG_H("Tx:%d, ip-type: %d ip-type not matching: %d Ignore\n",
   5756 					tx_index, tx_prop->tx[tx_index].ip, iptype);
   5757 			continue;
   5758 		}
   5759 
   5760 		if (rt_rule == NULL)
   5761 		{
   5762 			rt_rule = (struct ipa_ioc_mdfy_rt_rule *)
   5763 				calloc(1, sizeof(struct ipa_ioc_mdfy_rt_rule) +
   5764 						NUM * sizeof(struct ipa_rt_rule_mdfy));
   5765 
   5766 			if (rt_rule == NULL)
   5767 			{
   5768 				IPACMERR("Unable to allocate memory for modify rt rule\n");
   5769 				return;
   5770 			}
   5771 			IPACMDBG("Allocated memory for %d rules successfully\n", NUM);
   5772 
   5773 			rt_rule->commit = 1;
   5774 			rt_rule->num_rules = 0;
   5775 			rt_rule->ip = iptype;
   5776 		}
   5777 
   5778 		rt_rule_entry = &rt_rule->rules[rt_rule->num_rules];
   5779 
   5780 		memcpy(&rt_rule_entry->rule.attrib,
   5781 				&tx_prop->tx[tx_index].attrib,
   5782 				sizeof(rt_rule_entry->rule.attrib));
   5783 		rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   5784 
   5785 		if (iptype == IPA_IP_v4)
   5786 		{
   5787 			rt_rule_entry->rule.attrib.u.v4.dst_addr      = 0;
   5788 			rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0;
   5789 			rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v4;
   5790 			rt_rule_entry->rt_rule_hdl = wan_route_rule_v4_hdl[tx_index];
   5791 		}
   5792 		else
   5793 		{
   5794 			rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0;
   5795 			rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0;
   5796 			rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0;
   5797 			rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0;
   5798 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0;
   5799 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0;
   5800 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0;
   5801 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0;
   5802 
   5803 			rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v6;
   5804 			rt_rule_entry->rt_rule_hdl = wan_route_rule_v6_hdl[tx_index];
   5805 		}
   5806 		IPACMDBG_H("Header handle: 0x%x\n", rt_rule_entry->rule.hdr_hdl);
   5807 
   5808 		if (isSCCMode)
   5809 		{
   5810 			rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
   5811 		}
   5812 		else
   5813 		{
   5814 			IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
   5815 					tx_prop->tx[tx_index].alt_dst_pipe);
   5816 			rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
   5817 		}
   5818 
   5819 		rt_rule->num_rules++;
   5820 	}
   5821 
   5822 	if (rt_rule != NULL)
   5823 	{
   5824 
   5825 		if (rt_rule->num_rules > 0)
   5826 		{
   5827 			if (false == m_routing.ModifyRoutingRule(rt_rule))
   5828 			{
   5829 				IPACMERR("Routing rule modify failed!\n");
   5830 				free(rt_rule);
   5831 				return;
   5832 			}
   5833 
   5834 			IPACMDBG("Routing rule modified successfully \n");
   5835 		}
   5836 
   5837 		free(rt_rule);
   5838 	}
   5839 
   5840 	return;
   5841 }
   5842 
   5843 void IPACM_Wan::handle_wan_client_SCC_MCC_switch(bool isSCCMode, ipa_ip_type iptype)
   5844 {
   5845 	struct ipa_ioc_mdfy_rt_rule *rt_rule = NULL;
   5846 	struct ipa_rt_rule_mdfy *rt_rule_entry;
   5847 
   5848 	uint32_t tx_index = 0, clnt_index =0;
   5849 	int v6_num = 0;
   5850 	const int NUM_RULES = 1;
   5851 
   5852 	int size = sizeof(struct ipa_ioc_mdfy_rt_rule) +
   5853 		NUM_RULES * sizeof(struct ipa_rt_rule_mdfy);
   5854 
   5855 	IPACMDBG("isSCCMode: %d\n",isSCCMode);
   5856 
   5857 	if (tx_prop == NULL || is_default_gateway == false)
   5858 	{
   5859 		IPACMDBG_H("No tx properties or no default route set yet\n");
   5860 		return;
   5861 	}
   5862 
   5863 	rt_rule = (struct ipa_ioc_mdfy_rt_rule *)calloc(1, size);
   5864 	if (rt_rule == NULL)
   5865 	{
   5866 		IPACMERR("Unable to allocate memory for modify rt rule\n");
   5867 		return;
   5868 	}
   5869 
   5870 
   5871 	for (clnt_index = 0; clnt_index < num_wan_client; clnt_index++)
   5872 	{
   5873 		if (iptype == IPA_IP_v4)
   5874 		{
   5875 			IPACMDBG_H("wan client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n",
   5876 					clnt_index, iptype,
   5877 					get_client_memptr(wan_client, clnt_index)->ipv4_set,
   5878 					get_client_memptr(wan_client, clnt_index)->route_rule_set_v4);
   5879 
   5880 			if( get_client_memptr(wan_client, clnt_index)->route_rule_set_v4 == false ||
   5881 					get_client_memptr(wan_client, clnt_index)->ipv4_set == false)
   5882 			{
   5883 				continue;
   5884 			}
   5885 
   5886 			for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
   5887 			{
   5888 				if (iptype != tx_prop->tx[tx_index].ip)
   5889 				{
   5890 					IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d skip\n",
   5891 							tx_index, tx_prop->tx[tx_index].ip, iptype);
   5892 					continue;
   5893 				}
   5894 
   5895 				memset(rt_rule, 0, size);
   5896 				rt_rule->commit = 1;
   5897 				rt_rule->num_rules = NUM_RULES;
   5898 				rt_rule->ip = iptype;
   5899 				rt_rule_entry = &rt_rule->rules[0];
   5900 
   5901 				IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", clnt_index,
   5902 						get_client_memptr(wan_client, clnt_index)->v4_addr);
   5903 
   5904 				IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n",
   5905 						clnt_index,
   5906 						get_client_memptr(wan_client, clnt_index)->hdr_hdl_v4);
   5907 
   5908 				if (IPACM_Iface::ipacmcfg->isMCC_Mode == true)
   5909 				{
   5910 					IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
   5911 							tx_prop->tx[tx_index].alt_dst_pipe);
   5912 					rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
   5913 				}
   5914 				else
   5915 				{
   5916 					rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
   5917 				}
   5918 
   5919 				memcpy(&rt_rule_entry->rule.attrib,
   5920 						&tx_prop->tx[tx_index].attrib,
   5921 						sizeof(rt_rule_entry->rule.attrib));
   5922 				rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   5923 
   5924 				rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, clnt_index)->hdr_hdl_v4;
   5925 				rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wan_client, clnt_index)->v4_addr;
   5926 				rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
   5927 
   5928 				/* copy ipv4 RT rule hdl */
   5929 				IPACMDBG_H("rt rule hdl=%x\n",
   5930 						get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4);
   5931 
   5932 				rt_rule_entry->rt_rule_hdl =
   5933 					get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4;
   5934 
   5935 				if (false == m_routing.ModifyRoutingRule(rt_rule))
   5936 				{
   5937 					IPACMERR("Routing rule modify failed!\n");
   5938 					free(rt_rule);
   5939 					return;
   5940 				}
   5941 			}
   5942 		}
   5943 		else
   5944 		{
   5945 			IPACMDBG_H("wan client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", clnt_index, iptype,
   5946 					get_client_memptr(wan_client, clnt_index)->ipv6_set,
   5947 					get_client_memptr(wan_client, clnt_index)->route_rule_set_v6);
   5948 
   5949 			if( get_client_memptr(wan_client, clnt_index)->route_rule_set_v6 == 0)
   5950 			{
   5951 				continue;
   5952 			}
   5953 
   5954 			for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
   5955 			{
   5956 				if (iptype != tx_prop->tx[tx_index].ip)
   5957 				{
   5958 					IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d skip\n",
   5959 							tx_index, tx_prop->tx[tx_index].ip, iptype);
   5960 					continue;
   5961 				}
   5962 
   5963 				memset(rt_rule, 0, size);
   5964 				rt_rule->commit = 1;
   5965 				rt_rule->num_rules = NUM_RULES;
   5966 				rt_rule->ip = iptype;
   5967 				rt_rule_entry = &rt_rule->rules[0];
   5968 
   5969 				/* Modify only rules in v6 WAN RT TBL*/
   5970 				for (v6_num = 0;
   5971 						v6_num < get_client_memptr(wan_client, clnt_index)->route_rule_set_v6;
   5972 						v6_num++)
   5973 				{
   5974 					IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n",
   5975 							clnt_index,
   5976 							get_client_memptr(wan_client, clnt_index)->hdr_hdl_v6);
   5977 
   5978 					/* Downlink traffic from Wan iface, directly through IPA */
   5979 					if (IPACM_Iface::ipacmcfg->isMCC_Mode == true)
   5980 					{
   5981 						IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
   5982 								tx_prop->tx[tx_index].alt_dst_pipe);
   5983 						rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
   5984 					}
   5985 					else
   5986 					{
   5987 						rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
   5988 					}
   5989 
   5990 					memcpy(&rt_rule_entry->rule.attrib,
   5991 							&tx_prop->tx[tx_index].attrib,
   5992 							sizeof(rt_rule_entry->rule.attrib));
   5993 
   5994 					rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, clnt_index)->hdr_hdl_v6;
   5995 					rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   5996 					rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][0];
   5997 					rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][1];
   5998 					rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][2];
   5999 					rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][3];
   6000 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
   6001 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
   6002 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
   6003 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
   6004 
   6005 					IPACMDBG_H("rt rule hdl=%x\n",
   6006 							get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num]);
   6007 
   6008 					rt_rule_entry->rt_rule_hdl =
   6009 						get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num];
   6010 
   6011 					if (false == m_routing.ModifyRoutingRule(rt_rule))
   6012 					{
   6013 						IPACMERR("Routing rule Modify failed!\n");
   6014 						free(rt_rule);
   6015 						return;
   6016 					}
   6017 				}
   6018 			} /* end of for loop */
   6019 		}
   6020 
   6021 	}
   6022 
   6023 	free(rt_rule);
   6024 	return;
   6025 }
   6026 
   6027 /*handle eth client */
   6028 int IPACM_Wan::handle_network_stats_update(ipa_get_apn_data_stats_resp_msg_v01 *data)
   6029 {
   6030 	FILE *fp = NULL;
   6031 
   6032 	for (uint32_t apn_index =0; apn_index < data->apn_data_stats_list_len; apn_index++)
   6033 	{
   6034 		if(data->apn_data_stats_list[apn_index].mux_id == ext_prop->ext[0].mux_id)
   6035 		{
   6036 			IPACMDBG_H("Received IPA_TETHERING_STATS_UPDATE_NETWORK_STATS, MUX ID %d TX (P%lu/B%lu) RX (P%lu/B%lu)\n",
   6037 				data->apn_data_stats_list[apn_index].mux_id,
   6038 					data->apn_data_stats_list[apn_index].num_ul_packets,
   6039 						data->apn_data_stats_list[apn_index].num_ul_bytes,
   6040 							data->apn_data_stats_list[apn_index].num_dl_packets,
   6041 								data->apn_data_stats_list[apn_index].num_dl_bytes);
   6042 			fp = fopen(IPA_NETWORK_STATS_FILE_NAME, "w");
   6043 			if ( fp == NULL )
   6044 			{
   6045 				IPACMERR("Failed to write pipe stats to %s, error is %d - %s\n",
   6046 						IPA_NETWORK_STATS_FILE_NAME, errno, strerror(errno));
   6047 				return IPACM_FAILURE;
   6048 			}
   6049 
   6050 			fprintf(fp, NETWORK_STATS,
   6051 				dev_name,
   6052 					data->apn_data_stats_list[apn_index].num_ul_packets,
   6053 						data->apn_data_stats_list[apn_index].num_ul_bytes,
   6054 							data->apn_data_stats_list[apn_index].num_dl_packets,
   6055 								data->apn_data_stats_list[apn_index].num_dl_bytes);
   6056 			fclose(fp);
   6057 			break;
   6058 		};
   6059 	}
   6060 	return IPACM_SUCCESS;
   6061 }
   6062 
   6063 int IPACM_Wan::add_dummy_rx_hdr()
   6064 {
   6065 
   6066 #define IFACE_INDEX_LEN 2
   6067 	char index[IFACE_INDEX_LEN];
   6068 	struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL;
   6069 	int len = 0;
   6070 	struct ipa_ioc_copy_hdr sCopyHeader;
   6071 	struct ipa_hdr_add *ipv6_hdr;
   6072 	struct ethhdr *eth_ipv6;
   6073 	struct ipa_ioc_add_hdr_proc_ctx* pHeaderProcTable = NULL;
   6074 	uint32_t cnt;
   6075 
   6076 	/* get netdev-mac */
   6077 	if(tx_prop != NULL)
   6078 	{
   6079 		/* copy partial header for v6 */
   6080 		for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
   6081 		{
   6082 				 if(tx_prop->tx[cnt].ip==IPA_IP_v6)
   6083 				 {
   6084 								IPACMDBG_H("Got partial v6-header name from %d tx props\n", cnt);
   6085 								memset(&sCopyHeader, 0, sizeof(sCopyHeader));
   6086 								memcpy(sCopyHeader.name,
   6087 											 tx_prop->tx[cnt].hdr_name,
   6088 											 sizeof(sCopyHeader.name));
   6089 
   6090 								IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt);
   6091 								if (m_header.CopyHeader(&sCopyHeader) == false)
   6092 								{
   6093 									PERROR("ioctl copy header failed");
   6094 									return IPACM_FAILURE;
   6095 								}
   6096 
   6097 								IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
   6098 								IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst);
   6099 								if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE)
   6100 								{
   6101 									IPACMERR("header oversize\n");
   6102 									return IPACM_FAILURE;
   6103 								}
   6104 								else
   6105 								{
   6106 									/* copy client mac_addr to partial header */
   6107 									IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n",
   6108 											sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst);
   6109 									/* only copy 6 bytes mac-address */
   6110 									if(sCopyHeader.is_eth2_ofst_valid == false)
   6111 									{
   6112 										memcpy(netdev_mac, &sCopyHeader.hdr[0+IPA_MAC_ADDR_SIZE],
   6113 												sizeof(netdev_mac));
   6114 									}
   6115 									else
   6116 									{
   6117 										memcpy(netdev_mac, &sCopyHeader.hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE],
   6118 												sizeof(netdev_mac));
   6119 									}
   6120 								}
   6121 					break;
   6122 				}
   6123 		}
   6124 	}
   6125 
   6126 	len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add));
   6127 	pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len);
   6128 	if (pHeaderDescriptor == NULL)
   6129 	{
   6130 		IPACMERR("calloc failed to allocate pHeaderDescriptor\n");
   6131 		return IPACM_FAILURE;
   6132 	}
   6133 	ipv6_hdr = &pHeaderDescriptor->hdr[0];
   6134 	/* copy ethernet type to header */
   6135 	eth_ipv6 = (struct ethhdr *) (ipv6_hdr->hdr +2);
   6136 	memcpy(eth_ipv6->h_dest, netdev_mac, ETH_ALEN);
   6137 	memcpy(eth_ipv6->h_source, ext_router_mac_addr, ETH_ALEN);
   6138 	eth_ipv6->h_proto = htons(ETH_P_IPV6);
   6139 	pHeaderDescriptor->commit = true;
   6140 	pHeaderDescriptor->num_hdrs = 1;
   6141 
   6142 	memset(ipv6_hdr->name, 0,
   6143 			 sizeof(pHeaderDescriptor->hdr[0].name));
   6144 
   6145 	snprintf(index,sizeof(index), "%d", ipa_if_num);
   6146 	strlcpy(ipv6_hdr->name, index, sizeof(ipv6_hdr->name));
   6147 	ipv6_hdr->name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   6148 
   6149 	if (strlcat(ipv6_hdr->name, IPA_DUMMY_ETH_HDR_NAME_v6, sizeof(ipv6_hdr->name)) > IPA_RESOURCE_NAME_MAX)
   6150 	{
   6151 		IPACMERR(" header name construction failed exceed length (%zu)\n", strlen(ipv6_hdr->name));
   6152 		return IPACM_FAILURE;
   6153 	}
   6154 
   6155 	ipv6_hdr->hdr_len = ETH_HLEN + 2;
   6156 	ipv6_hdr->hdr_hdl = -1;
   6157 	ipv6_hdr->is_partial = 0;
   6158 	ipv6_hdr->status = -1;
   6159 	ipv6_hdr->type = IPA_HDR_L2_ETHERNET_II;
   6160 
   6161 	if (m_header.AddHeader(pHeaderDescriptor) == false ||
   6162 			ipv6_hdr->status != 0)
   6163 	{
   6164 		IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", ipv6_hdr->status);
   6165 		return IPACM_FAILURE;
   6166 	}
   6167 
   6168 	hdr_hdl_dummy_v6 = ipv6_hdr->hdr_hdl;
   6169 	IPACMDBG_H("dummy v6 full header name:%s header handle:(0x%x)\n",
   6170 								 ipv6_hdr->name,
   6171 								 hdr_hdl_dummy_v6);
   6172 	/* add dummy hdr_proc_hdl */
   6173 	len = sizeof(struct ipa_ioc_add_hdr_proc_ctx) + sizeof(struct ipa_hdr_proc_ctx_add);
   6174 	pHeaderProcTable = (ipa_ioc_add_hdr_proc_ctx*)malloc(len);
   6175 	if(pHeaderProcTable == NULL)
   6176 	{
   6177 		IPACMERR("Cannot allocate header processing table.\n");
   6178 		return IPACM_FAILURE;
   6179 	}
   6180 
   6181 	memset(pHeaderProcTable, 0, len);
   6182 	pHeaderProcTable->commit = 1;
   6183 	pHeaderProcTable->num_proc_ctxs = 1;
   6184 	pHeaderProcTable->proc_ctx[0].hdr_hdl = hdr_hdl_dummy_v6;
   6185 	if (m_header.AddHeaderProcCtx(pHeaderProcTable) == false)
   6186 	{
   6187 		IPACMERR("Adding dummy hhdr_proc_hdl failed with status: %d\n", pHeaderProcTable->proc_ctx[0].status);
   6188 		return IPACM_FAILURE;
   6189 	}
   6190 	else
   6191 	{
   6192 		hdr_proc_hdl_dummy_v6 = pHeaderProcTable->proc_ctx[0].proc_ctx_hdl;
   6193 		IPACMDBG_H("dummy hhdr_proc_hdl is added successfully. (0x%x)\n", hdr_proc_hdl_dummy_v6);
   6194 	}
   6195 	return IPACM_SUCCESS;
   6196 }
   6197