1 /*
2 Copyright (c) 2013-2020 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 #include <IPACM_Netlink.h>
56 #endif
57 
58 bool IPACM_Wan::wan_up = false;
59 bool IPACM_Wan::wan_up_v6 = false;
60 uint8_t IPACM_Wan::xlat_mux_id = 0;
61 
62 uint32_t IPACM_Wan::curr_wan_ip = 0;
63 int IPACM_Wan::num_v4_flt_rule = 0;
64 int IPACM_Wan::num_v6_flt_rule = 0;
65 
66 int IPACM_Wan::ipa_pm_q6_check = 0;
67 
68 struct ipa_flt_rule_add IPACM_Wan::flt_rule_v4[IPA_MAX_FLT_RULE];
69 struct ipa_flt_rule_add IPACM_Wan::flt_rule_v6[IPA_MAX_FLT_RULE];
70 
71 char IPACM_Wan::wan_up_dev_name[IF_NAME_LEN];
72 
73 ipacm_wan_iface_type IPACM_Wan::backhaul_mode = Q6_WAN;
74 bool IPACM_Wan::is_ext_prop_set = false;
75 
76 int IPACM_Wan::num_ipv4_modem_pdn = 0;
77 int IPACM_Wan::num_ipv6_modem_pdn = 0;
78 
79 bool IPACM_Wan::embms_is_on = false;
80 bool IPACM_Wan::backhaul_is_wan_bridge = false;
81 bool IPACM_Wan::is_xlat = false;
82 
83 ipacm_coalesce IPACM_Wan::coalesce_enable_info[IPA_MAX_NUM_SW_PDNS];
84 
85 uint32_t IPACM_Wan::backhaul_ipv6_prefix[2];
86 
87 #ifdef FEATURE_IPA_ANDROID
88 uint32_t	IPACM_Wan::ipa_if_num_tether_v4_total = 0;
89 uint32_t	IPACM_Wan::ipa_if_num_tether_v6_total = 0;
90 
91 int	IPACM_Wan::ipa_if_num_tether_v4[IPA_MAX_IFACE_ENTRIES];
92 int	IPACM_Wan::ipa_if_num_tether_v6[IPA_MAX_IFACE_ENTRIES];
93 #endif
94 
95 uint16_t IPACM_Wan::mtu_default_wan_v4 = DEFAULT_MTU_SIZE;
96 uint16_t IPACM_Wan::mtu_default_wan_v6 = DEFAULT_MTU_SIZE;
97 
IPACM_Wan(int iface_index,ipacm_wan_iface_type is_sta_mode,uint8_t * mac_addr)98 IPACM_Wan::IPACM_Wan(int iface_index,
99 	ipacm_wan_iface_type is_sta_mode,
100 	uint8_t *mac_addr) : IPACM_Iface(iface_index)
101 {
102 	num_firewall_v4 = 0;
103 	num_firewall_v6 = 0;
104 	wan_route_rule_v4_hdl = NULL;
105 	wan_route_rule_v6_hdl = NULL;
106 	wan_route_rule_v6_hdl_a5 = NULL;
107 	wan_client = NULL;
108 	mac_addr = NULL;
109 
110 	if(iface_query != NULL)
111 	{
112 		wan_route_rule_v4_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t));
113 		wan_route_rule_v6_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t));
114 		wan_route_rule_v6_hdl_a5 = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t));
115 		IPACMDBG_H("IPACM->IPACM_Wan(%d) constructor: Tx:%d\n", ipa_if_num, iface_query->num_tx_props);
116 	}
117 
118 	wan_v4_addr_set = false;
119 	wan_v4_addr_gw_set = false;
120 	wan_v6_addr_gw_set = false;
121 	active_v4 = false;
122 	active_v6 = false;
123 	header_set_v4 = false;
124 	header_set_v6 = false;
125 	header_partial_default_wan_v4 = false;
126 	header_partial_default_wan_v6 = false;
127 	hdr_hdl_sta_v4 = 0;
128 	hdr_hdl_sta_v6 = 0;
129 	num_ipv6_dest_flt_rule = 0;
130 	memset(ipv6_dest_flt_rule_hdl, 0, MAX_DEFAULT_v6_ROUTE_RULES*sizeof(uint32_t));
131 	memset(ipv6_prefix, 0, sizeof(ipv6_prefix));
132 	memset(wan_v6_addr_gw, 0, sizeof(wan_v6_addr_gw));
133 	ext_prop = NULL;
134 	is_ipv6_frag_firewall_flt_rule_installed = false;
135 	ipv6_frag_firewall_flt_rule_hdl = 0;
136 
137 	mtu_v4 = DEFAULT_MTU_SIZE;
138 	mtu_v4_set = false;
139 	mtu_v6 = DEFAULT_MTU_SIZE;
140 	mtu_v6_set = false;
141 
142 	num_wan_client = 0;
143 	header_name_count = 0;
144 	memset(invalid_mac, 0, sizeof(invalid_mac));
145 
146 	is_xlat_local = false;
147 	hdr_hdl_dummy_v6 = 0;
148 	hdr_proc_hdl_dummy_v6 = 0;
149 	is_default_gateway = false;
150 	m_fd_ipa = 0;
151 	wan_client_len = 0;
152 	m_is_sta_mode = is_sta_mode;
153 
154 #ifdef IPA_MTU_EVENT_MAX
155 	/* Query WAN MTU to handle IPACM restart scenarios. */
156 	if(is_sta_mode == Q6_WAN)
157 	{
158 		int fd_wwan_ioctl;
159 		ipa_mtu_info *mtu_info = (ipa_mtu_info *)malloc(sizeof(ipa_mtu_info));
160 		if (mtu_info)
161 		{
162 			memset(mtu_info, 0, sizeof(ipa_mtu_info));
163 			memcpy(mtu_info->if_name, dev_name, IPA_IFACE_NAME_LEN);
164 			fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
165 			if(fd_wwan_ioctl < 0)
166 			{
167 				IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME);
168 			}
169 			else
170 			{
171 				IPACMDBG_H("send WAN_IOC_GET_WAN_MTU for %s\n", mtu_info->if_name);
172 				if(ioctl(fd_wwan_ioctl, WAN_IOC_GET_WAN_MTU, mtu_info))
173 				{
174 					IPACMERR("Failed to send WAN_IOC_GET_WAN_MTU\n ");
175 				}
176 				else
177 				{
178 					/* Updated MTU values.*/
179 					if (mtu_info->mtu_v4)
180 					{
181 						mtu_v4 = mtu_info->mtu_v4;
182 						mtu_v4_set = true;
183 						IPACMDBG_H("Updated v4 mtu=[%d] for (%s)\n",
184 							mtu_v4, mtu_info->if_name);
185 					}
186 					if (mtu_info->mtu_v6)
187 					{
188 						mtu_v6 = mtu_info->mtu_v6;
189 						mtu_v6_set = true;
190 						IPACMDBG_H("Updated v6 mtu=[%d] for (%s)\n",
191 							mtu_v6, mtu_info->if_name);
192 					}
193 				}
194 				close(fd_wwan_ioctl);
195 			}
196 			free(mtu_info);
197 		}
198 	}
199 #endif
200 
201 	if(iface_query != NULL)
202 	{
203 		IPACMDBG_H("index:%d constructor: Tx properties:%d\n", iface_index, iface_query->num_tx_props);
204 
205 		if(is_sta_mode == Q6_WAN)
206 		{
207 			query_ext_prop();
208 
209 			if ((iface_query->num_ext_props == 1) && ((ext_prop != NULL) && ext_prop->ext[0].ip == IPA_IP_MAX))
210 			{
211 				/* only has one ext properties with IP_MAX type, will be the mhi-modem */
212 				IPACMDBG_H("One extended property for iface %s, replace %d to Q6_MHI_WAN\n", dev_name, is_sta_mode);
213 				m_is_sta_mode = Q6_MHI_WAN;
214 			}
215 			else
216 			{
217 				IPACMDBG_H("The new WAN interface is modem.\n");
218 				m_is_sta_mode = is_sta_mode;
219 				is_default_gateway = false;
220 			}
221 		}
222 		else
223 		{
224 			m_is_sta_mode = is_sta_mode;
225 			IPACMDBG_H("The new WAN interface is WLAN STA.\n");
226 		}
227 
228 		wan_client_len = (sizeof(ipa_wan_client)) + (iface_query->num_tx_props * sizeof(wan_client_rt_hdl));
229 		wan_client = (ipa_wan_client *)calloc(IPA_MAX_NUM_WAN_CLIENTS, wan_client_len);
230 		if (wan_client == NULL)
231 		{
232 			IPACMERR("unable to allocate memory\n");
233 			return;
234 		}
235 	}
236 	else
237 	{
238 		IPACMDBG_H("iface_query is empty.\n");
239 		return;
240 	}
241 
242 	m_fd_ipa = open(IPA_DEVICE_NAME, O_RDWR);
243 	if(0 == m_fd_ipa)
244 	{
245 		IPACMERR("Failed to open %s\n",IPA_DEVICE_NAME);
246 	}
247 
248 	if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == EMBMS_IF)
249 	{
250 		IPACMDBG(" IPACM->IPACM_Wan_eMBMS(%d)\n", ipa_if_num);
251 		embms_is_on = true;
252 		install_wan_filtering_rule(false);
253 		if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_None && IPACM_Iface::ipacmcfg->GetIPAVer() < IPA_HW_v4_0)
254 		{
255 			/* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */
256 			if(tx_prop != NULL)
257 			{
258 				IPACMDBG_H("dev %s add producer dependency\n", dev_name);
259 				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]);
260 				IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false);
261 			}
262 		}
263 	}
264 	else
265 	{
266 		IPACMDBG(" IPACM->IPACM_Wan(%d)\n", ipa_if_num);
267 	}
268 	return;
269 }
270 
~IPACM_Wan()271 IPACM_Wan::~IPACM_Wan()
272 {
273 	IPACM_EvtDispatcher::deregistr(this);
274 	IPACM_IfaceManager::deregistr(this);
275 	return;
276 }
277 
278 /* handle new_address event */
handle_addr_evt(ipacm_event_data_addr * data)279 int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data)
280 {
281 	struct ipa_ioc_add_rt_rule *rt_rule = NULL;
282 	struct ipa_rt_rule_add *rt_rule_entry;
283 	struct ipa_ioc_add_flt_rule *flt_rule;
284 	struct ipa_flt_rule_add flt_rule_entry;
285 	struct ipa_ioc_get_hdr hdr;
286 	bool result;
287 
288 	const int NUM_RULES = 1;
289 	uint32_t num_ipv6_addr;
290 	int res = IPACM_SUCCESS,len;
291 #ifdef FEATURE_IPACM_HAL
292 	IPACM_OffloadManager* OffloadMng;
293 #endif
294 
295 	memset(&hdr, 0, sizeof(hdr));
296 	if(tx_prop == NULL || rx_prop == NULL)
297 	{
298 		IPACMDBG_H("Either tx or rx property is NULL, return.\n");
299 		return IPACM_SUCCESS;
300 	}
301 
302 	/* Update the IP Type. */
303 	config_ip_type(data->iptype);
304 
305 	if (data->iptype == IPA_IP_v6)
306 	{
307 		for(num_ipv6_addr=0;num_ipv6_addr<num_dft_rt_v6;num_ipv6_addr++)
308 		{
309 			if((ipv6_addr[num_ipv6_addr][0] == data->ipv6_addr[0]) &&
310 			   (ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) &&
311 			   (ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) &&
312 			   (ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3]))
313 			{
314 				IPACMDBG_H("find matched ipv6 address, index:%d \n", num_ipv6_addr);
315 				return IPACM_SUCCESS;
316 				break;
317 			}
318 		}
319 		rt_rule = (struct ipa_ioc_add_rt_rule *)
320 			calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
321 				NUM_RULES * sizeof(struct ipa_rt_rule_add));
322 
323 		if (!rt_rule)
324 		{
325 			IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n");
326 			return IPACM_FAILURE;
327 		}
328 
329 		rt_rule->commit = 1;
330 		rt_rule->num_rules = NUM_RULES;
331 		rt_rule->ip = data->iptype;
332 		/* setup RT rule for v6_lan table*/
333 		strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name));
334 
335 		rt_rule_entry = &rt_rule->rules[0];
336 		rt_rule_entry->at_rear = false;
337 		rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
338 		rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0];
339 		rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1];
340 		rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2];
341 		rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = data->ipv6_addr[3];
342 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
343 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
344 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
345 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
346 		ipv6_addr[num_dft_rt_v6][0] = data->ipv6_addr[0];
347 		ipv6_addr[num_dft_rt_v6][1] = data->ipv6_addr[1];
348 		ipv6_addr[num_dft_rt_v6][2] = data->ipv6_addr[2];
349 		ipv6_addr[num_dft_rt_v6][3] = data->ipv6_addr[3];
350 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
351 			rt_rule_entry->rule.hashable = false;
352 		if(m_is_sta_mode == Q6_WAN)
353 		{
354 			strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
355 			hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
356 			if(m_header.GetHeaderHandle(&hdr) == false)
357 			{
358 				IPACMERR("Failed to get QMAP header.\n");
359 				return IPACM_FAILURE;
360 			}
361 			rt_rule_entry->rule.hdr_hdl = hdr.hdl;
362 			rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS;
363 			/* legacy default v4 rt-rule */
364 #ifdef IPA_RT_SUPPORT_COAL
365 			rt_rule_entry->rule.coalesce = false;
366 #endif
367 			/* legacy default v6 rt-rule */
368 			if (false == m_routing.AddRoutingRule(rt_rule))
369 			{
370 				IPACMERR("Routing rule addition failed!\n");
371 				res = IPACM_FAILURE;
372 				goto fail;
373 			}
374 			else if (rt_rule_entry->status)
375 			{
376 				IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
377 				res = rt_rule_entry->status;
378 				goto fail;
379 			}
380 			dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl;
381 
382 			/* setup same rule for v6_wan table*/
383 			strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name));
384 			if (false == m_routing.AddRoutingRule(rt_rule))
385 			{
386 				IPACMERR("Routing rule addition failed!\n");
387 				res = IPACM_FAILURE;
388 				goto fail;
389 		}
390 			else if (rt_rule_entry->status)
391 		{
392 				IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
393 				res = rt_rule_entry->status;
394 				goto fail;
395 		}
396 			dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl;
397 
398 			IPACMDBG_H("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, entry: %d %d\n",
399 					dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6],
400 					dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1],
401 					MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6,
402 					MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1);
403 			/* RSC TCP rule*/
404 			rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
405 			rt_rule_entry->rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP;
406 #ifdef IPA_RT_SUPPORT_COAL
407 			if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable)
408 				rt_rule_entry->rule.coalesce = true;
409 		else
410 				rt_rule_entry->rule.coalesce = false;
411 #endif
412 			if (false == m_routing.AddRoutingRule(rt_rule))
413 		{
414 				IPACMERR("Routing rule addition failed!\n");
415 				res = IPACM_FAILURE;
416 				goto fail;
417 			}
418 			else if (rt_rule_entry->status)
419 			{
420 				IPACMERR("rsc tcp rt rule adding failed. Result=%d\n", rt_rule_entry->status);
421 				res = rt_rule_entry->status;
422 				goto fail;
423 		}
424 			dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl;
425 			IPACMDBG_H("ipv6 wan iface rsc tcp rt-rule hdll=0x%x\n enable(%d), entry %d", dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6],
426 				IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable,
427 				2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6);
428 			/* RSB UDP rule*/
429 			rt_rule_entry->rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_UDP;
430 #ifdef IPA_RT_SUPPORT_COAL
431 			if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable)
432 				rt_rule_entry->rule.coalesce = true;
433 			else
434 				rt_rule_entry->rule.coalesce = false;
435 #endif
436 		if (false == m_routing.AddRoutingRule(rt_rule))
437 		{
438 			IPACMERR("Routing rule addition failed!\n");
439 			res = IPACM_FAILURE;
440 			goto fail;
441 		}
442 		else if (rt_rule_entry->status)
443 		{
444 				IPACMERR("rsb udp rt rule adding failed. Result=%d\n", rt_rule_entry->status);
445 				res = rt_rule_entry->status;
446 				goto fail;
447 			}
448 			dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl;
449 			IPACMDBG_H("ipv6 wan iface rsb udp rt-rule hdll=0x%x\n enable(%d) entry %d", dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1],
450 				IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable,
451 				2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1);
452 		}
453 		else
454 		{
455 			rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS;
456 			/* legacy default v6 rt-rule */
457 			if (false == m_routing.AddRoutingRule(rt_rule))
458 			{
459 				IPACMERR("Routing rule addition failed!\n");
460 				res = IPACM_FAILURE;
461 				goto fail;
462 			}
463 			else if (rt_rule_entry->status)
464 			{
465 			IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
466 			res = rt_rule_entry->status;
467 			goto fail;
468 		}
469 		dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl;
470 
471 		/* setup same rule for v6_wan table*/
472 		strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name));
473 		if (false == m_routing.AddRoutingRule(rt_rule))
474 		{
475 			IPACMERR("Routing rule addition failed!\n");
476 			res = IPACM_FAILURE;
477 			goto fail;
478 		}
479 		else if (rt_rule_entry->status)
480 		{
481 			IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
482 			res = rt_rule_entry->status;
483 			goto fail;
484 		}
485 		dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl;
486 
487 			IPACMDBG_H("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, entry: %d  %d\n",
488 				dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6],
489 					dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1],
490 					MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6,
491 					MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1);
492 		}
493 
494 		/* add default filtering rules when wan-iface get global v6-prefix */
495 		if (num_dft_rt_v6 == 1)
496 		{
497 			if(m_is_sta_mode == Q6_WAN)
498 			{
499 				modem_ipv6_pdn_index = num_ipv6_modem_pdn;
500 				num_ipv6_modem_pdn++;
501 				IPACMDBG_H("Now the number of modem ipv6 pdn is %d.\n", num_ipv6_modem_pdn);
502 				init_fl_rule_ex(data->iptype);
503 			}
504 			else if(m_is_sta_mode == Q6_MHI_WAN)
505 			{
506 				IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING for ip-family %d \n", dev_name, IPA_IP_v6);
507 				IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name, IPA_IP_v6);
508 			}
509 			else
510 			{
511 				init_fl_rule(data->iptype);
512 			}
513 		}
514 
515 		/* add WAN DL interface IP specific flt rule for IPv6 when backhaul is not Q6 */
516 		if(m_is_sta_mode != Q6_WAN)
517 		{
518 			if(rx_prop != NULL && is_global_ipv6_addr(data->ipv6_addr)
519 				&& num_ipv6_dest_flt_rule < MAX_DEFAULT_v6_ROUTE_RULES)
520 			{
521 				len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add);
522 
523 				flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
524 				if (!flt_rule)
525 				{
526 					IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
527 					return IPACM_FAILURE;
528 				}
529 
530 				flt_rule->commit = 1;
531 				flt_rule->ep = rx_prop->rx[0].src_pipe;
532 				flt_rule->global = false;
533 				flt_rule->ip = IPA_IP_v6;
534 				flt_rule->num_rules = 1;
535 
536 				memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
537 
538 				flt_rule_entry.rule.retain_hdr = 1;
539 				flt_rule_entry.rule.to_uc = 0;
540 				flt_rule_entry.rule.eq_attrib_type = 0;
541 				flt_rule_entry.at_rear = true;
542 				flt_rule_entry.flt_rule_hdl = -1;
543 				flt_rule_entry.status = -1;
544 				flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
545 				if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
546 					flt_rule_entry.rule.hashable = true;
547 				memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
548 
549 				flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
550 				memcpy(flt_rule_entry.rule.attrib.u.v6.dst_addr, data->ipv6_addr, sizeof(flt_rule_entry.rule.attrib.u.v6.dst_addr));
551 				flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
552 				flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
553 				flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
554 				flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
555 				memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
556 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
557 				/* use index hw-counter */
558 				if(IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
559 				{
560 					IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
561 					result = m_filtering.AddFilteringRule_hw_index(flt_rule, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL);
562 				} else {
563 					result = m_filtering.AddFilteringRule(flt_rule);
564 				}
565 #else
566 				result = m_filtering.AddFilteringRule(flt_rule);
567 #endif
568 
569 				if (result == false)
570 				{
571 					IPACMERR("Error Adding Filtering rule, aborting...\n");
572 					free(flt_rule);
573 					res = IPACM_FAILURE;
574 					goto fail;
575 				}
576 				else
577 				{
578 					IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
579 					ipv6_dest_flt_rule_hdl[num_ipv6_dest_flt_rule] = flt_rule->rules[0].flt_rule_hdl;
580 					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]);
581 					num_ipv6_dest_flt_rule++;
582 					free(flt_rule);
583 				}
584 			}
585 		}
586 		/* store ipv6 prefix if the ipv6 address is not link local */
587 		if(is_global_ipv6_addr(data->ipv6_addr))
588 		{
589 			memcpy(ipv6_prefix, data->ipv6_addr, sizeof(ipv6_prefix));
590 		}
591 	    num_dft_rt_v6++;
592     }
593 	else
594 	{
595 		if(wan_v4_addr_set)
596 		{
597 			/* check iface ipv4 same or not */
598 			if(data->ipv4_addr == wan_v4_addr)
599 			{
600 				IPACMDBG_H("Already setup device (%s) ipv4 and it didn't change(0x%x)\n", dev_name, data->ipv4_addr);
601 				return IPACM_SUCCESS;
602 			}
603 			else
604 			{
605 				IPACMDBG_H(" device (%s) ipv4 addr is changed\n", dev_name);
606 				/* Delete default Coalese v4 RT rule */
607 				if (m_is_sta_mode == Q6_WAN) {
608 					if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[0], IPA_IP_v4) == false)
609 					{
610 						IPACMERR("Routing old RSC TCP RT rule deletion failed!\n");
611 						res = IPACM_FAILURE;
612 						goto fail;
613 					}
614 					if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[1], IPA_IP_v4) == false)
615 					{
616 						IPACMERR("Routing old RSB UDP RT rule deletion failed!\n");
617 						res = IPACM_FAILURE;
618 						goto fail;
619 					}
620 				}
621 				/* Delete default v4 RT rule */
622 				IPACMDBG_H("Delete default v4 routing rules\n");
623 				if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
624 				{
625 					IPACMERR("Routing old RT rule deletion failed!\n");
626 					res = IPACM_FAILURE;
627 					goto fail;
628 				}
629 			}
630 		}
631 
632 		rt_rule = (struct ipa_ioc_add_rt_rule *)
633 			 calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
634 							NUM_RULES * sizeof(struct ipa_rt_rule_add));
635 
636 		if (!rt_rule)
637 		{
638 			IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n");
639 			return IPACM_FAILURE;
640 		}
641 
642 		rt_rule->commit = 1;
643 		rt_rule->num_rules = NUM_RULES;
644 		rt_rule->ip = data->iptype;
645 		rt_rule_entry = &rt_rule->rules[0];
646 		rt_rule_entry->at_rear = false;
647 		rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
648 		/* still need setup v4 default routing rule to A5*/
649 		strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name));
650 		rt_rule_entry->rule.attrib.u.v4.dst_addr      = data->ipv4_addr;
651 		rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
652 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
653 			rt_rule_entry->rule.hashable = false;
654 		if(m_is_sta_mode == Q6_WAN)
655 		{
656 			/* query qmap header*/
657 			strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
658 			hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
659 			if(m_header.GetHeaderHandle(&hdr) == false)
660 			{
661 				IPACMERR("Failed to get QMAP header.\n");
662 				res = IPACM_FAILURE;
663 				goto fail;
664 			}
665 			rt_rule_entry->rule.hdr_hdl = hdr.hdl;
666 			rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS;
667 			/* legacy default v4 rt-rule */
668 #ifdef IPA_RT_SUPPORT_COAL
669 			rt_rule_entry->rule.coalesce = false;
670 #endif
671 			/* legacy default v4 rt-rule */
672 			if (false == m_routing.AddRoutingRule(rt_rule))
673 			{
674 				IPACMERR("Routing rule addition failed!\n");
675 				res = IPACM_FAILURE;
676 				goto fail;
677 			}
678 			else if (rt_rule_entry->status)
679 			{
680 				IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
681 				res = rt_rule_entry->status;
682 				goto fail;
683 		}
684 			dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
685 			IPACMDBG_H("ipv4 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[0]);
686 			/* RSC TCP rule*/
687 			rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
688 			rt_rule_entry->rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP;
689 
690 #ifdef IPA_RT_SUPPORT_COAL
691 			if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable)
692 				rt_rule_entry->rule.coalesce = true;
693 		else
694 				rt_rule_entry->rule.coalesce = false;
695 #endif
696 			if (false == m_routing.AddRoutingRule(rt_rule))
697 		{
698 				IPACMERR("Routing rule addition failed!\n");
699 				res = IPACM_FAILURE;
700 				goto fail;
701 			}
702 			else if (rt_rule_entry->status)
703 			{
704 				IPACMERR("rsc tcp rt rule adding failed. Result=%d\n", rt_rule_entry->status);
705 				res = rt_rule_entry->status;
706 				goto fail;
707 		}
708 			dft_coalesce_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
709 			IPACMDBG_H("ipv4 wan iface rsc tcp rt-rule hdll=0x%x\n enable(%d)", dft_coalesce_rt_rule_hdl[0],
710 				IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable);
711 
712 			/* RSB UDP rule*/
713 			rt_rule_entry->rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_UDP;
714 #ifdef IPA_RT_SUPPORT_COAL
715 			if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable)
716 				rt_rule_entry->rule.coalesce = true;
717 			else
718 				rt_rule_entry->rule.coalesce = false;
719 #endif
720 		if (false == m_routing.AddRoutingRule(rt_rule))
721 		{
722 			IPACMERR("Routing rule addition failed!\n");
723 			res = IPACM_FAILURE;
724 			goto fail;
725 		}
726 		else if (rt_rule_entry->status)
727 		{
728 				IPACMERR("rsb udp rt rule adding failed. Result=%d\n", rt_rule_entry->status);
729 				res = rt_rule_entry->status;
730 				goto fail;
731 			}
732 			dft_coalesce_rt_rule_hdl[1] = rt_rule_entry->rt_rule_hdl;
733 			IPACMDBG_H("ipv4 wan iface rsb udp rt-rule hdll=0x%x\n enable(%d)", dft_coalesce_rt_rule_hdl[1],
734 				IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable);
735 		}
736 		else
737 		{
738 			rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS;
739 			/* legacy default v4 rt-rule */
740 			if (false == m_routing.AddRoutingRule(rt_rule))
741 			{
742 				IPACMERR("Routing rule addition failed!\n");
743 				res = IPACM_FAILURE;
744 				goto fail;
745 			}
746 			else if (rt_rule_entry->status)
747 			{
748 			IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
749 			res = rt_rule_entry->status;
750 			goto fail;
751 		}
752 		dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
753 		IPACMDBG_H("ipv4 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[0]);
754 		}
755 
756 			/* initial multicast/broadcast/fragment filter rule */
757 		/* only do one time */
758 		if(!wan_v4_addr_set)
759 		{
760 			/* initial multicast/broadcast/fragment filter rule */
761 			if(m_is_sta_mode == Q6_WAN)
762 			{
763 				modem_ipv4_pdn_index = num_ipv4_modem_pdn;
764 				num_ipv4_modem_pdn++;
765 				IPACMDBG_H("Now the number of modem ipv4 pdn is %d.\n", num_ipv4_modem_pdn);
766 				init_fl_rule_ex(data->iptype);
767 			}
768 			else if(m_is_sta_mode == Q6_MHI_WAN)
769 			{
770 				IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING for ip-family %d \n", dev_name, IPA_IP_v4);
771 				IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name, IPA_IP_v4);
772 			}
773 			else
774 			{
775 				init_fl_rule(data->iptype);
776 			}
777 		}
778 
779 		wan_v4_addr = data->ipv4_addr;
780 		wan_v4_addr_set = true;
781 
782 		if (m_is_sta_mode == Q6_WAN)
783 			curr_wan_ip = data->ipv4_addr;
784 
785 		IPACMDBG_H("Receved wan ipv4-addr:0x%x\n",wan_v4_addr);
786 	}
787 
788 #ifdef FEATURE_IPACM_HAL
789 	/* check if having pending set_upstream cache*/
790 	OffloadMng = IPACM_OffloadManager::GetInstance();
791 	if (OffloadMng == NULL) {
792 		IPACMERR("failed to get IPACM_OffloadManager instance !\n");
793 	} else {
794 		IPACMDBG_H(" check iface %s if having set_upstream cache events\n", dev_name);
795 		OffloadMng->search_framwork_cache(dev_name);
796 	}
797 #endif
798 	IPACMDBG_H("number of default route rules %d\n", num_dft_rt_v6);
799 
800 fail:
801 	if (rt_rule != NULL)
802 	{
803 		free(rt_rule);
804 	}
805 	return res;
806 }
807 
808 /* handle new_address event */
handle_addr_evt_mhi_q6(ipacm_event_data_addr * data)809 int IPACM_Wan::handle_addr_evt_mhi_q6(ipacm_event_data_addr *data)
810 {
811 	uint32_t num_ipv6_addr;
812 	int res = IPACM_SUCCESS;
813 	struct ipa_ioc_add_rt_rule *rt_rule = NULL;
814 	struct ipa_rt_rule_add *rt_rule_entry;
815 	struct ipa_ioc_get_hdr hdr;
816 	const int NUM_RULES = 1;
817 
818 #ifdef FEATURE_IPACM_HAL
819 	IPACM_OffloadManager* OffloadMng;
820 #endif
821 
822 	memset(&hdr, 0, sizeof(hdr));
823 	if(tx_prop == NULL || rx_prop == NULL)
824 	{
825 		IPACMDBG_H("Either tx or rx property is NULL, return.\n");
826 		return IPACM_SUCCESS;
827 	}
828 	/* Update the IP Type. */
829 	config_ip_type(data->iptype);
830 
831 	if (data->iptype == IPA_IP_v6)
832 	{
833 		for(num_ipv6_addr=0;num_ipv6_addr<num_dft_rt_v6;num_ipv6_addr++)
834 		{
835 			if((ipv6_addr[num_ipv6_addr][0] == data->ipv6_addr[0]) &&
836 			   (ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) &&
837 			   (ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) &&
838 			   (ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3]))
839 			{
840 				IPACMDBG_H("find matched ipv6 address, index:%d \n", num_ipv6_addr);
841 				return IPACM_SUCCESS;
842 				break;
843 			}
844 		}
845 
846 		ipv6_addr[num_dft_rt_v6][0] = data->ipv6_addr[0];
847 		ipv6_addr[num_dft_rt_v6][1] = data->ipv6_addr[1];
848 		ipv6_addr[num_dft_rt_v6][2] = data->ipv6_addr[2];
849 		ipv6_addr[num_dft_rt_v6][3] = data->ipv6_addr[3];
850 
851 		/* store ipv6 prefix if the ipv6 address is not link local */
852 		if(is_global_ipv6_addr(data->ipv6_addr))
853 		{
854 			memcpy(ipv6_prefix, data->ipv6_addr, sizeof(ipv6_prefix));
855 		}
856 		num_dft_rt_v6++;
857 		if (num_dft_rt_v6 == 1)
858 		{
859 			/* Add Natting iface to IPACM_Config if there is  Rx/Tx property */
860 			if (rx_prop != NULL || tx_prop != NULL)
861 			{
862 				IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING for ip-family %d \n", dev_name, IPA_IP_v6);
863 				IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name, IPA_IP_v6);
864 			}
865 			/* setup v6-wan-tbl */
866 			rt_rule = (struct ipa_ioc_add_rt_rule *)
867 				calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
868 				NUM_RULES * sizeof(struct ipa_rt_rule_add));
869 			if (!rt_rule)
870 			{
871 				IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n");
872 				return IPACM_FAILURE;
873 			}
874 
875 			rt_rule->commit = 1;
876 			rt_rule->num_rules = NUM_RULES;
877 			rt_rule->ip = data->iptype;
878 			strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name));
879 			rt_rule_entry = &rt_rule->rules[0];
880 			strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
881 			hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
882 			if(m_header.GetHeaderHandle(&hdr) == false)
883 			{
884 				IPACMERR("Failed to get QMAP header.\n");
885 				free(rt_rule);
886 				return IPACM_FAILURE;
887 			}
888 			rt_rule_entry->rule.hdr_hdl = hdr.hdl;
889 			rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS;
890 			rt_rule_entry->at_rear = false;
891 			rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
892 			/* still need setup v4 default routing rule to A5*/
893 			rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
894 			rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0];
895 			rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1];
896 			rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2];
897 			rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = data->ipv6_addr[3];
898 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
899 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
900 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
901 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
902 			ipv6_addr[0][0] = data->ipv6_addr[0];
903 			ipv6_addr[0][1] = data->ipv6_addr[1];
904 			ipv6_addr[0][2] = data->ipv6_addr[2];
905 			ipv6_addr[0][3] = data->ipv6_addr[3];
906 			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
907 				rt_rule_entry->rule.hashable = false;
908 			if (false == m_routing.AddRoutingRule(rt_rule))
909 			{
910 				IPACMERR("Routing rule addition failed!\n");
911 				free(rt_rule);
912 				return IPACM_FAILURE;
913 			}
914 			else if (rt_rule_entry->status)
915 			{
916 				IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
917 				free(rt_rule);
918 				return rt_rule_entry->status;
919 			}
920 			dft_rt_rule_hdl[1] = rt_rule_entry->rt_rule_hdl;
921 			IPACMDBG_H("ipv6 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[1]);
922 		}
923 	}
924 	else
925 	{
926 		if(wan_v4_addr_set)
927 		{
928 			/* check iface ipv4 same or not */
929 			if(data->ipv4_addr == wan_v4_addr)
930 			{
931 				IPACMDBG_H("Already setup device (%s) ipv4 and it didn't change(0x%x)\n", dev_name, data->ipv4_addr);
932 				return IPACM_SUCCESS;
933 			}
934 			else
935 			{
936 				IPACMDBG_H(" device (%s) ipv4 addr is changed\n", dev_name);
937 				/* Delete default v4 RT rule */
938 				IPACMDBG_H("Delete default v4 routing rules\n");
939 				if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
940 				{
941 					IPACMERR("Routing old RT rule deletion failed!\n");
942 					return IPACM_FAILURE;
943 				}
944 			}
945 		}
946 		/* only do one time */
947 		if(!wan_v4_addr_set)
948 		{
949 			/* Add Natting iface to IPACM_Config if there is  Rx/Tx property */
950 			if (rx_prop != NULL || tx_prop != NULL)
951 			{
952 				IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING for ip-family %d \n", dev_name, IPA_IP_v4);
953 				IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name, IPA_IP_v4);
954 			}
955 
956 			rt_rule = (struct ipa_ioc_add_rt_rule *)
957 				calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
958 					NUM_RULES * sizeof(struct ipa_rt_rule_add));
959 
960 			if (!rt_rule)
961 			{
962 				IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n");
963 				return IPACM_FAILURE;
964 			}
965 
966 			rt_rule->commit = 1;
967 			rt_rule->num_rules = NUM_RULES;
968 			rt_rule->ip = data->iptype;
969 			rt_rule_entry = &rt_rule->rules[0];
970 			strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
971 			hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
972 			if(m_header.GetHeaderHandle(&hdr) == false)
973 			{
974 				IPACMERR("Failed to get QMAP header.\n");
975 				free(rt_rule);
976 				return IPACM_FAILURE;
977 			}
978 			rt_rule_entry->rule.hdr_hdl = hdr.hdl;
979 			rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS;
980 			rt_rule_entry->at_rear = false;
981 			rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
982 			/* still need setup v4 default routing rule to A5*/
983 			strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name));
984 			rt_rule_entry->rule.attrib.u.v4.dst_addr      = data->ipv4_addr;
985 			rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
986 			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
987 				rt_rule_entry->rule.hashable = false;
988 			if (false == m_routing.AddRoutingRule(rt_rule))
989 			{
990 				IPACMERR("Routing rule addition failed!\n");
991 				free(rt_rule);
992 				return IPACM_FAILURE;
993 			}
994 			else if (rt_rule_entry->status)
995 			{
996 				IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
997 				free(rt_rule);
998 				return rt_rule_entry->status;
999 			}
1000 			dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
1001 			IPACMDBG_H("ipv4 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[0]);
1002 		}
1003 
1004 		wan_v4_addr = data->ipv4_addr;
1005 		wan_v4_addr_set = true;
1006 		IPACMDBG_H("Receved wan ipv4-addr:0x%x\n",wan_v4_addr);
1007 		free(rt_rule);
1008 	}
1009 
1010 #ifdef FEATURE_IPACM_HAL
1011 	/* check if having pending set_upstream cache*/
1012 	OffloadMng = IPACM_OffloadManager::GetInstance();
1013 	if (OffloadMng == NULL) {
1014 		IPACMERR("failed to get IPACM_OffloadManager instance !\n");
1015 	} else {
1016 		IPACMDBG_H(" check iface %s if having set_upstream cache events\n", dev_name);
1017 		OffloadMng->search_framwork_cache(dev_name);
1018 	}
1019 #endif
1020 	IPACMDBG_H("number of default route rules %d\n", num_dft_rt_v6);
1021 
1022 	return res;
1023 }
event_callback(ipa_cm_event_id event,void * param)1024 void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param)
1025 {
1026 	int ipa_interface_index;
1027 
1028 	switch (event)
1029 	{
1030 	case IPA_WLAN_LINK_DOWN_EVENT:
1031 		{
1032 			if(m_is_sta_mode == WLAN_WAN)
1033 			{
1034 				ipacm_event_data_fid *data = (ipacm_event_data_fid *)param;
1035 				ipa_interface_index = iface_ipa_index_query(data->if_index);
1036 				if (ipa_interface_index == ipa_if_num)
1037 				{
1038 					IPACMDBG_H("Received IPA_WLAN_LINK_DOWN_EVENT\n");
1039 					handle_down_evt();
1040 					/* reset the STA-iface category to unknown */
1041 					IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat = UNKNOWN_IF;
1042 					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);
1043 					IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
1044 					delete this;
1045 					return;
1046 				}
1047 			}
1048 		}
1049 		break;
1050 
1051 	case IPA_WAN_XLAT_CONNECT_EVENT:
1052 		{
1053 			IPACMDBG_H("Recieved IPA_WAN_XLAT_CONNECT_EVENT\n");
1054 			ipacm_event_data_fid *data = (ipacm_event_data_fid *)param;
1055 			ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data->if_index);
1056 			if ((ipa_interface_index == ipa_if_num) && (m_is_sta_mode == Q6_WAN))
1057 			{
1058 				is_xlat_local = true;
1059 				IPACMDBG_H("WAN-LTE (%s) link up, iface: %d is_xlat_local: %d\n",
1060 						IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,data->if_index, is_xlat_local);
1061 			}
1062 			break;
1063 		}
1064 	case IPA_CFG_CHANGE_EVENT:
1065 		{
1066 			if ( (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ipa_if_cate) &&
1067 					(m_is_sta_mode ==ECM_WAN))
1068 			{
1069 				IPACMDBG_H("Received IPA_CFG_CHANGE_EVENT and category did not change(wan_mode:%d)\n", m_is_sta_mode);
1070 				IPACMDBG_H("Now the cradle wan mode is %d.\n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode);
1071 				if(is_default_gateway == true)
1072 				{
1073 					if(backhaul_is_wan_bridge == false && IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == BRIDGE)
1074 					{
1075 						IPACMDBG_H("Cradle wan mode switch to bridge mode.\n");
1076 						backhaul_is_wan_bridge = true;
1077 					}
1078 					else if(backhaul_is_wan_bridge == true && IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
1079 					{
1080 						IPACMDBG_H("Cradle wan mode switch to router mode.\n");
1081 						backhaul_is_wan_bridge = false;
1082 					}
1083 					else
1084 					{
1085 						IPACMDBG_H("No cradle mode switch, return.\n");
1086 						return;
1087 					}
1088 					/* post wan mode change event to LAN/WLAN */
1089 					if(IPACM_Wan::wan_up == true)
1090 					{
1091 						IPACMDBG_H("This interface is default GW.\n");
1092 						ipacm_cmd_q_data evt_data;
1093 						memset(&evt_data, 0, sizeof(evt_data));
1094 
1095 						ipacm_event_cradle_wan_mode *data_wan_mode = NULL;
1096 						data_wan_mode = (ipacm_event_cradle_wan_mode *)malloc(sizeof(ipacm_event_cradle_wan_mode));
1097 						if(data_wan_mode == NULL)
1098 						{
1099 							IPACMERR("unable to allocate memory.\n");
1100 							return;
1101 						}
1102 						data_wan_mode->cradle_wan_mode = IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode;
1103 						evt_data.event = IPA_CRADLE_WAN_MODE_SWITCH;
1104 						evt_data.evt_data = data_wan_mode;
1105 						IPACMDBG_H("Posting IPA_CRADLE_WAN_MODE_SWITCH event.\n");
1106 						IPACM_EvtDispatcher::PostEvt(&evt_data);
1107 					}
1108 					/* update the firewall flt rule actions */
1109 					if(active_v4)
1110 					{
1111 						del_dft_firewall_rules(IPA_IP_v4);
1112 						config_dft_firewall_rules(IPA_IP_v4);
1113 					}
1114 					if(active_v6)
1115 					{
1116 						del_dft_firewall_rules(IPA_IP_v6);
1117 						config_dft_firewall_rules(IPA_IP_v6);
1118 					}
1119 				}
1120 				else
1121 				{
1122 					IPACMDBG_H("This interface is not default GW, ignore.\n");
1123 				}
1124 			}
1125 			else if ( (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat != ipa_if_cate) &&
1126 					(m_is_sta_mode ==ECM_WAN))
1127 			{
1128 				IPACMDBG_H("Received IPA_CFG_CHANGE_EVENT and category changed(wan_mode:%d)\n", m_is_sta_mode);
1129 				/* posting link-up event for cradle use-case */
1130 				ipacm_cmd_q_data evt_data;
1131 				memset(&evt_data, 0, sizeof(evt_data));
1132 
1133 				ipacm_event_data_fid *data_fid = NULL;
1134 				data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid));
1135 				if(data_fid == NULL)
1136 				{
1137 					IPACMERR("unable to allocate memory for IPA_USB_LINK_UP_EVENT data_fid\n");
1138 					return;
1139 				}
1140 				if(IPACM_Iface::ipa_get_if_index(dev_name, &(data_fid->if_index)))
1141 				{
1142 					IPACMERR("Error while getting interface index for %s device", dev_name);
1143 				}
1144 				evt_data.event = IPA_USB_LINK_UP_EVENT;
1145 				evt_data.evt_data = data_fid;
1146 				IPACMDBG_H("Posting event:%d\n", evt_data.event);
1147 				IPACM_EvtDispatcher::PostEvt(&evt_data);
1148 
1149 				/* delete previous instance */
1150 				handle_down_evt();
1151 				IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
1152 				delete this;
1153 				return;
1154 			}
1155 		}
1156 		break;
1157 
1158 	case IPA_COALESCE_NOTICE:
1159 		{
1160 			if (m_is_sta_mode == Q6_WAN)
1161 			{
1162 				IPACMDBG_H("Received IPA_COALESCE_NOTICE (wan_mode:%d)\n", m_is_sta_mode);
1163 				handle_coalesce_evt();
1164 			}
1165 		}
1166 		break;
1167 
1168 	case IPA_LINK_DOWN_EVENT:
1169 		{
1170 			ipacm_event_data_fid *data = (ipacm_event_data_fid *)param;
1171 			ipa_interface_index = iface_ipa_index_query(data->if_index);
1172 			if (ipa_interface_index == ipa_if_num)
1173 			{
1174 				if(m_is_sta_mode == Q6_WAN)
1175 				{
1176 						IPACMDBG_H("Received IPA_LINK_DOWN_EVENT\n");
1177 						handle_down_evt_ex();
1178 						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);
1179 						IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
1180 						delete this;
1181 						return;
1182 				}
1183 				else if ((m_is_sta_mode == ECM_WAN) || (m_is_sta_mode == Q6_MHI_WAN))
1184 				{
1185 					IPACMDBG_H("Received IPA_LINK_DOWN_EVENT(wan_mode:%d)\n", m_is_sta_mode);
1186 					/* delete previous instance */
1187 					handle_down_evt();
1188 					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);
1189 					IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
1190 					delete this;
1191 					return;
1192 				}
1193 			}
1194 		}
1195 		break;
1196 
1197 	case IPA_ADDR_ADD_EVENT:
1198 		{
1199 			ipacm_event_data_addr *data = (ipacm_event_data_addr *)param;
1200 			ipa_interface_index = iface_ipa_index_query(data->if_index);
1201 
1202 			if ( (data->iptype == IPA_IP_v4 && data->ipv4_addr == 0) ||
1203 					 (data->iptype == IPA_IP_v6 &&
1204 						data->ipv6_addr[0] == 0 && data->ipv6_addr[1] == 0 &&
1205 					  data->ipv6_addr[2] == 0 && data->ipv6_addr[3] == 0) )
1206 			{
1207 				IPACMDBG_H("Invalid address, ignore IPA_ADDR_ADD_EVENT event\n");
1208 				return;
1209 			}
1210 
1211 			if (ipa_interface_index == ipa_if_num)
1212 			{
1213 				IPACMDBG_H("Get IPA_ADDR_ADD_EVENT: IF ip type %d, incoming ip type %d\n", ip_type, data->iptype);
1214 				/* check v4 not setup before, v6 can have 2 iface ip */
1215 				if( (data->iptype == IPA_IP_v4)
1216 				    || ((data->iptype==IPA_IP_v6) && (num_dft_rt_v6!=MAX_DEFAULT_v6_ROUTE_RULES)))
1217 				{
1218 					if (m_is_sta_mode == Q6_MHI_WAN)
1219 					{
1220 						IPACMDBG_H("Got handle_addr_evt_mhi_q6 ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6);
1221 						handle_addr_evt_mhi_q6(data);
1222 					}
1223 					else
1224 					{
1225 						IPACMDBG_H("Got handle_addr_evt ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6);
1226 						handle_addr_evt(data);
1227 					}
1228 					/* checking if SW-RT_enable */
1229 					if (IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true &&
1230 							m_is_sta_mode != Q6_WAN)
1231 					{
1232 						/* handle software routing enable event*/
1233 						IPACMDBG_H("IPA_SW_ROUTING_ENABLE for iface: %s \n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name);
1234 
1235 						if(m_is_sta_mode == Q6_MHI_WAN)
1236 						{
1237 							handle_software_routing_enable(true);
1238 						}
1239 						else
1240 						{
1241 							handle_software_routing_enable(false);
1242 						}
1243 					}
1244 
1245 				}
1246 			}
1247 		}
1248 		break;
1249 
1250 
1251 	case IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT:
1252 		{
1253 			ipacm_event_data_iptype *data = (ipacm_event_data_iptype *)param;
1254 			ipa_interface_index = iface_ipa_index_query(data->if_index);
1255 #ifndef FEATURE_IPACM_HAL
1256 			/* add the check see if tether_iface is valid or not */
1257 			if (iface_ipa_index_query(data->if_index_tether) == INVALID_IFACE)
1258 			{
1259 				IPACMERR("UPSTREAM_ROUTE_ADD tether_if(%d), not valid ignore\n", INVALID_IFACE);
1260 				return;
1261 			}
1262 #endif
1263 			if (ipa_interface_index == ipa_if_num)
1264 			{
1265 				IPACMDBG_H("Received IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT (Android) for ip-type (%d)\n", data->iptype);
1266 				/* The special below condition is to handle default gateway */
1267 				if ((data->iptype == IPA_IP_v4) && (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX))
1268 				{
1269 					if (active_v4 == false)
1270 					{
1271 #ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN
1272 						IPACMDBG_H("adding routing table(upstream), dev (%s) ip-type(%d) default gw (%x)\n", dev_name,data->iptype, wan_v4_addr_gw);
1273 						wan_v4_addr_gw = data->ipv4_addr_gw;
1274 						wan_v4_addr_gw_set = true;
1275 						/* Check & construct STA header */
1276 						handle_sta_header_add_evt();
1277 #else
1278 						IPACMDBG_H("adding routing table(upstream), dev (%s) ip-type(%d)\n", dev_name,data->iptype);
1279 #endif
1280 						if (active_v4 == false)
1281 						{
1282 							handle_route_add_evt(data->iptype);
1283 						}
1284 					}
1285 #ifdef FEATURE_IPA_ANDROID
1286 #ifndef FEATURE_IPACM_HAL
1287 					/* Fixed CR 2438491 for HAL-android platform trgets.
1288 					   Need to revisit for non-hal-android-platform targets if issue could be reproduced there as well */
1289 					/* using ipa_if_index, not netdev_index */
1290 					post_wan_up_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether));
1291 #endif
1292 #endif
1293 				}
1294 				else if ((data->iptype == IPA_IP_v6) && (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX))
1295 				{
1296 					if(ipv6_prefix[0] == 0 && ipv6_prefix[1] == 0)
1297 					{
1298 						IPACMDBG_H("IPv6 default route comes earlier than global IP, ignore.\n");
1299 						return;
1300 					}
1301 
1302 					if (active_v6 == false)
1303 					{
1304 						IPACMDBG_H("\n get default v6 route (dst:00.00.00.00) upstream\n");
1305 #ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN
1306 						IPACMDBG_H(" IPV6 gateway: %08x:%08x:%08x:%08x \n",
1307 								data->ipv6_addr_gw[0], data->ipv6_addr_gw[1], data->ipv6_addr_gw[2], data->ipv6_addr_gw[3]);
1308 						wan_v6_addr_gw[0] = data->ipv6_addr_gw[0];
1309 						wan_v6_addr_gw[1] = data->ipv6_addr_gw[1];
1310 						wan_v6_addr_gw[2] = data->ipv6_addr_gw[2];
1311 						wan_v6_addr_gw[3] = data->ipv6_addr_gw[3];
1312 						wan_v6_addr_gw_set = true;
1313 						/* Check & construct STA header */
1314 						handle_sta_header_add_evt();
1315 #endif
1316 						if (active_v6 == false)
1317 						{
1318 							handle_route_add_evt(data->iptype);
1319 						}
1320 					}
1321 				}
1322 #ifdef FEATURE_IPA_ANDROID
1323 #ifndef FEATURE_IPACM_HAL
1324 				/* using ipa_if_index, not netdev_index */
1325 				post_wan_up_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether));
1326 #endif
1327 #endif
1328 
1329 			}
1330 			else /* double check if current default iface is not itself */
1331 			{
1332 				if ((data->iptype == IPA_IP_v4) && (active_v4 == true))
1333 				{
1334 					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);
1335 					IPACMDBG_H("need clean default v4 route (dst:0.0.0.0) for old iface (%s)\n", dev_name);
1336 					wan_v4_addr_gw_set = false;
1337 					if(m_is_sta_mode == Q6_WAN)
1338 					{
1339 						del_wan_firewall_rule(IPA_IP_v4);
1340 						install_wan_filtering_rule(false);
1341 						handle_route_del_evt_ex(IPA_IP_v4);
1342 					}
1343 					else if(m_is_sta_mode == Q6_MHI_WAN)
1344 					{
1345 						/* only need cleanup rt-rule*/
1346 						handle_route_del_evt(IPA_IP_v4);
1347 					}
1348 					else
1349 					{
1350 						del_dft_firewall_rules(IPA_IP_v4);
1351 						handle_route_del_evt(IPA_IP_v4);
1352 					}
1353 				}
1354 				else if ((data->iptype == IPA_IP_v6) && (active_v6 == true))
1355 				{
1356 				    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);
1357 					IPACMDBG_H("need clean default v6 route for old iface (%s)\n", dev_name);
1358 					if(m_is_sta_mode == Q6_WAN)
1359 					{
1360 						del_wan_firewall_rule(IPA_IP_v6);
1361 						install_wan_filtering_rule(false);
1362 						handle_route_del_evt_ex(IPA_IP_v6);
1363 					}
1364 					else if(m_is_sta_mode == Q6_MHI_WAN)
1365 					{
1366 						/* only need cleanup rt-rule*/
1367 						handle_route_del_evt(IPA_IP_v6);
1368 					}
1369 					else
1370 					{
1371 						del_dft_firewall_rules(IPA_IP_v6);
1372 						handle_route_del_evt(IPA_IP_v6);
1373 					}
1374 				}
1375 			}
1376 		}
1377 		break;
1378 
1379 	case IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT:
1380 		{
1381 			ipacm_event_data_iptype *data = (ipacm_event_data_iptype *)param;
1382 			ipa_interface_index = iface_ipa_index_query(data->if_index);
1383 #ifndef FEATURE_IPACM_HAL
1384 			/* add the check see if tether_iface is valid or not */
1385 			if (iface_ipa_index_query(data->if_index_tether) == INVALID_IFACE)
1386 			{
1387 				IPACMERR("UPSTREAM_ROUTE_DEL tether_if(%d), not valid ignore\n", INVALID_IFACE);
1388 				return;
1389 			}
1390 #endif
1391 			if (ipa_interface_index == ipa_if_num)
1392 			{
1393 				IPACMDBG_H("Received IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT\n");
1394 				if ((data->iptype == IPA_IP_v4) && (active_v4 == true))
1395 				{
1396 					IPACMDBG_H("get del default v4 route (dst:0.0.0.0)\n");
1397 					wan_v4_addr_gw_set = false;
1398 #ifdef FEATURE_IPA_ANDROID
1399 #ifdef FEATURE_IPACM_HAL
1400 					post_wan_down_tether_evt(data->iptype, 0);
1401 #else
1402 					/* using ipa_if_index, not netdev_index */
1403 					post_wan_down_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether));
1404 					/* no any ipv4 tether iface support*/
1405 					if(IPACM_Wan::ipa_if_num_tether_v4_total != 0)
1406 					{
1407 						IPACMDBG_H("still have tether ipv4 client on upsteam iface\n");
1408 						return;
1409 					}
1410 #endif
1411 #endif
1412 					if(m_is_sta_mode == Q6_WAN)
1413 					{
1414 						del_wan_firewall_rule(IPA_IP_v4);
1415 						install_wan_filtering_rule(false);
1416 						handle_route_del_evt_ex(IPA_IP_v4);
1417 					}
1418 					else if(m_is_sta_mode == Q6_MHI_WAN)
1419 					{
1420 						/* only need cleanup rt-rule*/
1421 						del_dft_firewall_rules(IPA_IP_v4);
1422 						handle_route_del_evt(IPA_IP_v4);
1423 					}
1424 					else
1425 					{
1426 						del_dft_firewall_rules(IPA_IP_v4);
1427 						handle_route_del_evt(IPA_IP_v4);
1428 					}
1429 				}
1430 				else if ((data->iptype == IPA_IP_v6) && (active_v6 == true))
1431 				{
1432 #ifdef FEATURE_IPA_ANDROID
1433 #ifdef FEATURE_IPACM_HAL
1434 					post_wan_down_tether_evt(data->iptype, 0);
1435 #else
1436 
1437 					/* using ipa_if_index, not netdev_index */
1438 					post_wan_down_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether));
1439 					/* no any ipv6 tether iface support*/
1440 					if(IPACM_Wan::ipa_if_num_tether_v6_total != 0)
1441 					{
1442 						IPACMDBG_H("still have tether ipv6 client on upsteam iface\n");
1443 						return;
1444 					}
1445 #endif
1446 #endif
1447 					if(m_is_sta_mode == Q6_WAN)
1448 					{
1449 						del_wan_firewall_rule(IPA_IP_v6);
1450 						install_wan_filtering_rule(false);
1451 						handle_route_del_evt_ex(IPA_IP_v6);
1452 					}
1453 					else if(m_is_sta_mode == Q6_MHI_WAN)
1454 					{
1455 						/* only need cleanup rt-rule*/
1456 						del_dft_firewall_rules(IPA_IP_v6);
1457 						handle_route_del_evt(IPA_IP_v6);
1458 					}
1459 
1460 					else
1461 					{
1462 						del_dft_firewall_rules(IPA_IP_v6);
1463 						handle_route_del_evt(IPA_IP_v6);
1464 					}
1465 				}
1466 			}
1467 		}
1468 		break;
1469 	case IPA_NETWORK_STATS_UPDATE_EVENT:
1470 		{
1471 			ipa_get_apn_data_stats_resp_msg_v01 *data = (ipa_get_apn_data_stats_resp_msg_v01 *)param;
1472 			if (!data->apn_data_stats_list_valid)
1473 			{
1474 				IPACMERR("not valid APN\n");
1475 				return;
1476 			}
1477 			else
1478 			{
1479 				handle_network_stats_update(data);
1480 			}
1481 		}
1482 		break;
1483 	case IPA_ROUTE_ADD_EVENT:
1484 		{
1485 			ipacm_event_data_addr *data = (ipacm_event_data_addr *)param;
1486 			ipa_interface_index = iface_ipa_index_query(data->if_index);
1487 			if (ipa_interface_index == ipa_if_num)
1488 			{
1489 				IPACMDBG_H("Received IPA_ROUTE_ADD_EVENT\n");
1490 				IPACMDBG_H("ipv4 addr 0x%x\n", data->ipv4_addr);
1491 				IPACMDBG_H("ipv4 addr mask 0x%x\n", data->ipv4_addr_mask);
1492 
1493 				/* The special below condition is to handle default gateway */
1494 				if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == false)
1495 					&& (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX))
1496 				{
1497 					wan_v4_addr_gw = data->ipv4_addr_gw;
1498 					wan_v4_addr_gw_set = true;
1499 					IPACMDBG_H("adding routing table, dev (%s) ip-type(%d), default gw (%x)\n", dev_name,data->iptype, wan_v4_addr_gw);
1500 					/* Check & construct STA header */
1501 					handle_sta_header_add_evt();
1502 					handle_route_add_evt(data->iptype);
1503 					/* Add IPv6 routing table if XLAT is enabled */
1504 					if(is_xlat_local && (m_is_sta_mode == Q6_WAN) && (active_v6 == false))
1505 					{
1506 						IPACMDBG_H("XLAT enabled: adding IPv6 routing table dev (%s)\n", dev_name);
1507 						handle_route_add_evt(IPA_IP_v6);
1508 					}
1509 				}
1510 				else if ((data->iptype == IPA_IP_v6) &&
1511 						(!data->ipv6_addr[0]) && (!data->ipv6_addr[1]) && (!data->ipv6_addr[2]) && (!data->ipv6_addr[3]) &&
1512 						(active_v6 == false) &&	(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX))
1513 				{
1514 					if(ipv6_prefix[0] == 0 && ipv6_prefix[1] == 0)
1515 					{
1516 						IPACMDBG_H("IPv6 default route comes earlier than global IP, ignore.\n");
1517 						return;
1518 					}
1519 
1520 					IPACMDBG_H("\n get default v6 route (dst:00.00.00.00)\n");
1521 					IPACMDBG_H(" IPV6 dst: %08x:%08x:%08x:%08x \n",
1522 							data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]);
1523 					IPACMDBG_H(" IPV6 gateway: %08x:%08x:%08x:%08x \n",
1524 							data->ipv6_addr_gw[0], data->ipv6_addr_gw[1], data->ipv6_addr_gw[2], data->ipv6_addr_gw[3]);
1525 					wan_v6_addr_gw[0] = data->ipv6_addr_gw[0];
1526 					wan_v6_addr_gw[1] = data->ipv6_addr_gw[1];
1527 					wan_v6_addr_gw[2] = data->ipv6_addr_gw[2];
1528 					wan_v6_addr_gw[3] = data->ipv6_addr_gw[3];
1529 					wan_v6_addr_gw_set = true;
1530 					/* Check & construct STA header */
1531 					handle_sta_header_add_evt();
1532 					handle_route_add_evt(data->iptype);
1533 				}
1534 			}
1535 			else /* double check if current default iface is not itself */
1536 			{
1537 				if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == true))
1538 				{
1539 					IPACMDBG_H("Received v4 IPA_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
1540 					IPACMDBG_H("ipv4 addr 0x%x\n", data->ipv4_addr);
1541 					IPACMDBG_H("ipv4 addr mask 0x%x\n", data->ipv4_addr_mask);
1542 					IPACMDBG_H("need clean default v4 route (dst:0.0.0.0) for old iface (%s)\n", dev_name);
1543 					wan_v4_addr_gw_set = false;
1544 					if(m_is_sta_mode == Q6_WAN)
1545 					{
1546 						del_wan_firewall_rule(IPA_IP_v4);
1547 						install_wan_filtering_rule(false);
1548 						handle_route_del_evt_ex(IPA_IP_v4);
1549 					}
1550 					else
1551 					{
1552 						del_dft_firewall_rules(IPA_IP_v4);
1553 						handle_route_del_evt(IPA_IP_v4);
1554 					}
1555 				}
1556 				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))
1557 				{
1558 				    IPACMDBG_H("Received v6 IPA_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name);
1559 					IPACMDBG_H("need clean default v6 route for old iface (%s)\n", dev_name);
1560 					if(m_is_sta_mode == Q6_WAN)
1561 					{
1562 						del_wan_firewall_rule(IPA_IP_v6);
1563 						install_wan_filtering_rule(false);
1564 						handle_route_del_evt_ex(IPA_IP_v6);
1565 					}
1566 					else
1567 					{
1568 						del_dft_firewall_rules(IPA_IP_v6);
1569 						handle_route_del_evt(IPA_IP_v6);
1570 					}
1571 				}
1572 			}
1573 		}
1574 		break;
1575 
1576 	case IPA_ROUTE_DEL_EVENT:
1577 		{
1578 			ipacm_event_data_addr *data = (ipacm_event_data_addr *)param;
1579 			ipa_interface_index = iface_ipa_index_query(data->if_index);
1580 			if (ipa_interface_index == ipa_if_num)
1581 			{
1582 				IPACMDBG_H("Received IPA_ROUTE_DEL_EVENT\n");
1583 				if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == true))
1584 				{
1585 					IPACMDBG_H("get del default v4 route (dst:0.0.0.0)\n");
1586 					wan_v4_addr_gw_set = false;
1587 					if(m_is_sta_mode == Q6_WAN)
1588 					{
1589 						del_wan_firewall_rule(IPA_IP_v4);
1590 						install_wan_filtering_rule(false);
1591 						handle_route_del_evt_ex(IPA_IP_v4);
1592 
1593 						if(is_xlat_local && active_v6 == true)
1594 						{
1595 							IPACMDBG_H("XLAT enabled: Delete IPv6 routing table dev (%s)\n", dev_name);
1596 							del_wan_firewall_rule(IPA_IP_v6);
1597 							install_wan_filtering_rule(false);
1598 							handle_route_del_evt_ex(IPA_IP_v6);
1599 						}
1600 					}
1601 					else
1602 					{
1603 						del_dft_firewall_rules(IPA_IP_v4);
1604 						handle_route_del_evt(IPA_IP_v4);
1605 					}
1606 				}
1607 				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))
1608 				{
1609 
1610 					IPACMDBG_H("get del default v6 route (dst:00.00.00.00)\n");
1611 					if(m_is_sta_mode == Q6_WAN)
1612 					{
1613 						del_wan_firewall_rule(IPA_IP_v6);
1614 						install_wan_filtering_rule(false);
1615 						handle_route_del_evt_ex(IPA_IP_v6);
1616 					}
1617 					else
1618 					{
1619 						del_dft_firewall_rules(IPA_IP_v6);
1620 						handle_route_del_evt(IPA_IP_v6);
1621 					}
1622 				}
1623 			}
1624 		}
1625 		break;
1626 
1627 	case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT:
1628 		{
1629 			ipacm_event_data_all *data = (ipacm_event_data_all *)param;
1630 			ipa_interface_index = iface_ipa_index_query(data->if_index);
1631 			int index = 0;
1632 			bool renew = false;
1633 
1634 			if (ipa_interface_index == ipa_if_num)
1635 			{
1636 				IPACMDBG_H("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT in STA mode\n");
1637 
1638 				if (m_is_sta_mode == WLAN_WAN)
1639 				{
1640 					if (data->iptype == IPA_IP_v4 && data->ipv4_addr == wan_v4_addr)
1641 					{
1642 						IPACMDBG_H("Ignore IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT in STA mode\n");
1643 						IPACMDBG_H("for its own ipv4 address\n");
1644 						return;
1645 					}
1646 					else if (data->iptype == IPA_IP_v6)
1647 					{
1648 						for (uint32_t num_ipv6_addr = 0; num_ipv6_addr < num_dft_rt_v6; num_ipv6_addr++)
1649 						{
1650 							if ((ipv6_addr[num_ipv6_addr][0] == data->ipv6_addr[0]) &&
1651 								(ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) &&
1652 								(ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) &&
1653 								(ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3]))
1654 							{
1655 								IPACMDBG_H("Ignore IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT in STA mode\n");
1656 								IPACMDBG_H("for its own ipv6 address\n");
1657 								return;
1658 							}
1659 						}
1660 					}
1661 				}
1662 
1663 				IPACMDBG_H("wan-iface got client \n");
1664 
1665 				/* first construc WAN-client full header */
1666 				if(memcmp(data->mac_addr,
1667 						invalid_mac,
1668 						sizeof(data->mac_addr)) == 0)
1669 				{
1670 					IPACMDBG_H("Received invalid Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
1671 					 data->mac_addr[0], data->mac_addr[1], data->mac_addr[2],
1672 					 data->mac_addr[3], data->mac_addr[4], data->mac_addr[5]);
1673 					return;
1674 				}
1675 
1676 				/* check if same as GW_ip need replacing */
1677 				if( handle_gw_mac_renew(data, index) == IPACM_SUCCESS)
1678 				{
1679 					renew = true;
1680 					IPACMDBG_H("Renew is happening with client-index (%d)\n", index);
1681 					/* clinet renew procedure */
1682 					handle_wan_hdr_init(data->mac_addr, true, index);
1683 				}
1684 				else
1685 				{
1686 					IPACMDBG_H("Renew is no need!\n");
1687 					handle_wan_hdr_init(data->mac_addr);
1688 				}
1689 
1690 				IPACMDBG_H("construct wan-client header and route rules \n");
1691 				/* Associate with IP and construct RT-rule */
1692 				if (handle_wan_client_ipaddr(data) == IPACM_FAILURE)
1693 				{
1694 					return;
1695 				}
1696 				handle_wan_client_route_rule(data->mac_addr, data->iptype);
1697 				/* Check & construct STA header */
1698 				handle_sta_header_add_evt(renew);
1699 				return;
1700 			}
1701 		}
1702 		break;
1703 
1704 	case IPA_SW_ROUTING_ENABLE:
1705 		IPACMDBG_H("Received IPA_SW_ROUTING_ENABLE\n");
1706 		/* handle software routing enable event */
1707 		if(m_is_sta_mode == Q6_WAN)
1708 		{
1709 			install_wan_filtering_rule(true);
1710 		}
1711 		else if(m_is_sta_mode == Q6_MHI_WAN)
1712 		{
1713 			handle_software_routing_enable(true);
1714 		}
1715 		else
1716 		{
1717 			handle_software_routing_enable(false);
1718 		}
1719 		break;
1720 
1721 	case IPA_SW_ROUTING_DISABLE:
1722 		IPACMDBG_H("Received IPA_SW_ROUTING_DISABLE\n");
1723 		/* handle software routing disable event */
1724 		if(m_is_sta_mode == Q6_WAN)
1725 		{
1726 			/* send current DL rules to modem */
1727 			install_wan_filtering_rule(false);
1728 			softwarerouting_act = false;
1729 		}
1730 		else if(m_is_sta_mode == Q6_MHI_WAN)
1731 		{
1732 			handle_software_routing_disable(true);
1733 		}
1734 		else
1735 		{
1736 			handle_software_routing_disable(false);
1737 		}
1738 		break;
1739 
1740 	case IPA_FIREWALL_CHANGE_EVENT:
1741 		IPACMDBG_H("Received IPA_FIREWALL_CHANGE_EVENT\n");
1742 
1743 		if(m_is_sta_mode == Q6_WAN)
1744 		{
1745 			if(is_default_gateway == false)
1746 			{
1747 				IPACMDBG_H("Interface %s is not default gw, return.\n", dev_name);
1748 				return;
1749 			}
1750 
1751 			if(ip_type == IPA_IP_v4)
1752 			{
1753 				del_wan_firewall_rule(IPA_IP_v4);
1754 				config_wan_firewall_rule(IPA_IP_v4);
1755 				install_wan_filtering_rule(false);
1756 			}
1757 			else if(ip_type == IPA_IP_v6)
1758 			{
1759 				del_wan_firewall_rule(IPA_IP_v6);
1760 				config_wan_firewall_rule(IPA_IP_v6);
1761 				install_wan_filtering_rule(false);
1762 			}
1763 			else if(ip_type == IPA_IP_MAX)
1764 			{
1765 				del_wan_firewall_rule(IPA_IP_v4);
1766 				config_wan_firewall_rule(IPA_IP_v4);
1767 
1768 				del_wan_firewall_rule(IPA_IP_v6);
1769 				config_wan_firewall_rule(IPA_IP_v6);
1770 				install_wan_filtering_rule(false);
1771 			}
1772 			else
1773 			{
1774 				IPACMERR("IP type is not expected.\n");
1775 			}
1776 		}
1777 		else
1778 		{
1779 			if (active_v4)
1780 			{
1781 				del_dft_firewall_rules(IPA_IP_v4);
1782 				config_dft_firewall_rules(IPA_IP_v4);
1783 			}
1784 			if (active_v6)
1785 			{
1786 
1787 				del_dft_firewall_rules(IPA_IP_v6);
1788 				config_dft_firewall_rules(IPA_IP_v6);
1789 			}
1790 		}
1791 		break;
1792 
1793 	case IPA_WLAN_SWITCH_TO_SCC:
1794 		if(IPACM_Wan::backhaul_mode == WLAN_WAN)
1795 		{
1796 			IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_SCC\n");
1797 			if(ip_type == IPA_IP_MAX)
1798 			{
1799 				handle_wlan_SCC_MCC_switch(true, IPA_IP_v4);
1800 				handle_wlan_SCC_MCC_switch(true, IPA_IP_v6);
1801 				handle_wan_client_SCC_MCC_switch(true, IPA_IP_v4);
1802 				handle_wan_client_SCC_MCC_switch(true, IPA_IP_v6);
1803 			}
1804 			else
1805 			{
1806 				handle_wlan_SCC_MCC_switch(true, ip_type);
1807 				handle_wan_client_SCC_MCC_switch(true, ip_type);
1808 			}
1809 		}
1810 		break;
1811 
1812 	case IPA_WLAN_SWITCH_TO_MCC:
1813 		if(IPACM_Wan::backhaul_mode == WLAN_WAN)
1814 		{
1815 			IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_MCC\n");
1816 			if(ip_type == IPA_IP_MAX)
1817 			{
1818 				handle_wlan_SCC_MCC_switch(false, IPA_IP_v4);
1819 				handle_wlan_SCC_MCC_switch(false, IPA_IP_v6);
1820 				handle_wan_client_SCC_MCC_switch(false, IPA_IP_v4);
1821 				handle_wan_client_SCC_MCC_switch(false, IPA_IP_v6);
1822 			}
1823 			else
1824 			{
1825 				handle_wlan_SCC_MCC_switch(false, ip_type);
1826 				handle_wan_client_SCC_MCC_switch(false, ip_type);
1827 			}
1828 		}
1829 		break;
1830 #ifdef FEATURE_IPACM_HAL
1831 	/* WA for WLAN to clean up NAT instance during SSR */
1832 	case IPA_SSR_NOTICE:
1833 	case IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE:
1834 	{
1835 		IPACMDBG_H("Received IPA_SSR_NOTICE event.\n");
1836 		if(m_is_sta_mode == WLAN_WAN)
1837 		{
1838 			IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
1839 		}
1840 	}
1841 	break;
1842 #endif
1843 #ifdef IPA_MTU_EVENT_MAX
1844 	case IPA_MTU_SET:
1845 	{
1846 		ipacm_event_mtu_info *data = (ipacm_event_mtu_info *)param;
1847 		ipa_mtu_info *mtu_info = &(data->mtu_info);
1848 		ipa_interface_index = iface_ipa_index_query(data->if_index);
1849 
1850 		if (ipa_interface_index == ipa_if_num)
1851 		{
1852 			IPACMDBG_H("Received IPA_MTU_SET (Android) for interface (%d)\n",
1853 				ipa_interface_index);
1854 			if (mtu_info->ip_type == IPA_IP_v4 || mtu_info->ip_type == IPA_IP_MAX)
1855 			{
1856 				/* Update v4_mtu. */
1857 				mtu_v4 = mtu_info->mtu_v4;
1858 				mtu_v4_set = true;
1859 
1860 				if (active_v4)
1861 				{
1862 					/* upstream interface. update default MTU. */
1863 					mtu_default_wan_v4 = mtu_v4;
1864 				}
1865 				IPACMDBG_H("Updated v4 mtu=[%d] for (%s), upstream_mtu=[%d]\n",
1866 					mtu_v4, mtu_info->if_name, mtu_default_wan_v4);
1867 			}
1868 			if (mtu_info->ip_type == IPA_IP_v6 || mtu_info->ip_type == IPA_IP_MAX)
1869 			{
1870 				/* Update v4_mtu. */
1871 				mtu_v6 = mtu_info->mtu_v6;
1872 				mtu_v6_set = true;
1873 				if (active_v6)
1874 				{
1875 					/* upstream interface. update default MTU. */
1876 					mtu_default_wan_v6 = mtu_v6;
1877 				}
1878 				IPACMDBG_H("Updated v6 mtu=[%d] for (%s), upstream_mtu=[%d]\n",
1879 					mtu_v6, mtu_info->if_name, mtu_default_wan_v6);
1880 			}
1881 
1882 			if (active_v4 || active_v6)
1883 			{
1884 				ipacm_event_mtu_info *mtu_event;
1885 				ipacm_cmd_q_data evt_data;
1886 				mtu_event = (ipacm_event_mtu_info *)malloc(sizeof(*mtu_event));
1887 				if(mtu_event == NULL)
1888 				{
1889 					IPACMERR("Failed to allocate memory.\n");
1890 					return;
1891 				}
1892 				memcpy(&mtu_event->mtu_info, mtu_info, sizeof(ipa_mtu_info));
1893 				evt_data.event = IPA_MTU_UPDATE;
1894 				evt_data.evt_data = mtu_event;
1895 				/* finish command queue */
1896 				IPACMDBG_H("Posting IPA_MTU_UPDATE event\n");
1897 				IPACM_EvtDispatcher::PostEvt(&evt_data);
1898 			}
1899 		}
1900 	}
1901 	break;
1902 #endif
1903 
1904 	default:
1905 		break;
1906 	}
1907 
1908 	return;
1909 }
1910 
1911 /* wan default route/filter rule configuration */
handle_route_add_evt(ipa_ip_type iptype,bool add_only)1912 int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype, bool add_only)
1913 {
1914 	/* add default WAN route */
1915 	struct ipa_ioc_add_rt_rule *rt_rule = NULL;
1916 	struct ipa_rt_rule_add *rt_rule_entry;
1917 	uint32_t tx_index = 0;
1918 	const int NUM = 1;
1919 	ipacm_cmd_q_data evt_data;
1920 	struct ipa_ioc_get_hdr hdr;
1921 	bool result;
1922 #ifdef	WAN_IOC_NOTIFY_WAN_STATE //resolve compile issue on 4.9 kernel
1923 	struct wan_ioctl_notify_wan_state wan_state;
1924 	int fd_wwan_ioctl;
1925 	memset(&wan_state, 0, sizeof(wan_state));
1926 #endif
1927 	IPACMDBG_H("ip-type:%d\n", iptype);
1928 
1929 	/* copy header from tx-property, see if partial or not */
1930 	/* assume all tx-property uses the same header name for v4 or v6*/
1931 
1932 	if(tx_prop == NULL)
1933 	{
1934 		IPACMDBG_H("No tx properties, ignore default route setting\n");
1935 		return IPACM_SUCCESS;
1936 	}
1937 
1938 	is_default_gateway = true;
1939 	IPACMDBG_H("Default route is added to iface %s.\n", dev_name);
1940 
1941 	if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == BRIDGE)
1942 	{
1943 		IPACM_Wan::backhaul_is_wan_bridge = true;
1944 	}
1945 	else
1946 	{
1947 		IPACM_Wan::backhaul_is_wan_bridge = false;
1948 	}
1949 	IPACMDBG_H("backhaul_is_wan_bridge ?: %d \n", IPACM_Wan::backhaul_is_wan_bridge);
1950 
1951 	/* query MTU size of the interface if MTU is not set via ioctl. */
1952 	if (!mtu_v4_set && !mtu_v6_set)
1953 	{
1954 		if(query_mtu_size())
1955 		{
1956 			IPACMERR("Failed to query mtu");
1957 		}
1958 	}
1959 
1960 	if (m_is_sta_mode ==Q6_WAN)
1961 	{
1962 		IPACM_Wan::backhaul_mode = m_is_sta_mode;
1963 		IPACMDBG_H("reset backhaul to LTE \n");
1964 
1965 		if (iface_query != NULL && iface_query->num_ext_props > 0)
1966 		{
1967 			if(ext_prop == NULL)
1968 			{
1969 				IPACMERR("Extended property is empty.\n");
1970 				return IPACM_FAILURE;
1971 			}
1972 			else
1973 			{
1974 				IPACM_Iface::ipacmcfg->SetQmapId(ext_prop->ext[0].mux_id);
1975 				IPACMDBG_H("Setting up QMAP ID %d.\n", ext_prop->ext[0].mux_id);
1976 			}
1977 		}
1978 		else
1979 		{
1980 			IPACMERR("iface_query is empty.\n");
1981 			return IPACM_FAILURE;
1982 		}
1983 	}
1984 	else if (m_is_sta_mode == Q6_MHI_WAN)
1985 	{
1986 		if (iface_query != NULL && iface_query->num_ext_props > 0)
1987 		{
1988 			/* treat Q6_MHI_WAN as STA mode also */
1989 			IPACMDBG_H("Q6-MHI  ipv4/v6-header already constructed \n");
1990 			IPACM_Wan::backhaul_mode = m_is_sta_mode;
1991 			IPACMDBG_H("Setting up QMAP ID %d.\n", ext_prop->ext[0].mux_id);
1992 			IPACM_Iface::ipacmcfg->SetQmapId(ext_prop->ext[0].mux_id);
1993 			/* sending mux-id info to PCIE-modem for UL */
1994 			if(false == m_filtering.AddOffloadFilteringRule(NULL, ext_prop->ext[0].mux_id, 0))
1995 			{
1996 				IPACMERR("Failed to send mux id info to modem.\n");
1997 				return IPACM_FAILURE;
1998 			}
1999 			/* send UL UDP frag filtering rule */
2000 			if(iptype==IPA_IP_v4 && add_offload_frag_rule())
2001 			{
2002 				IPACMERR("Failed to send DL frag rule to modem.\n");
2003 				return IPACM_FAILURE;
2004 			}
2005 
2006 			/* send ipv6 ICMP filtering rule */
2007 			if(iptype==IPA_IP_v6 && add_icmpv6_exception_rule())
2008 			{
2009 				IPACMERR("Failed to send ICMPv6 ex rule to modem.\n");
2010 				return IPACM_FAILURE;
2011 			}
2012 
2013 			/* send ipv4 TCP FIN filtering rule */
2014 			if(iptype==IPA_IP_v4 && add_tcp_fin_rst_exception_rule())
2015 			{
2016 				IPACMERR("Failed to send TCP FIN RST rule to modem.\n");
2017 				return IPACM_FAILURE;
2018 			}
2019 		}
2020 		else
2021 		{
2022 			IPACMERR("iface_query is empty.\n");
2023 			return IPACM_FAILURE;
2024 		}
2025 	}
2026 	else
2027 	{
2028 		IPACM_Wan::backhaul_mode = m_is_sta_mode;
2029 		if((iptype==IPA_IP_v4) && (header_set_v4 != true))
2030 		{
2031 			header_partial_default_wan_v4 = true;
2032 			IPACMDBG_H("STA ipv4-header haven't constructed \n");
2033 			return IPACM_SUCCESS;
2034 		}
2035 		else if((iptype==IPA_IP_v6) && (header_set_v6 != true))
2036 		{
2037 			header_partial_default_wan_v6 = true;
2038 			IPACMDBG_H("STA ipv6-header haven't constructed \n");
2039 			return IPACM_SUCCESS;
2040 		}
2041 	}
2042 
2043 	rt_rule = (struct ipa_ioc_add_rt_rule *)
2044 		 calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
2045 						NUM * sizeof(struct ipa_rt_rule_add));
2046 
2047 	if (!rt_rule)
2048 	{
2049 		IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n");
2050 		return IPACM_FAILURE;
2051 	}
2052 
2053 	rt_rule->commit = 1;
2054 	rt_rule->num_rules = (uint8_t)NUM;
2055 	rt_rule->ip = iptype;
2056 
2057 	rt_rule_entry = &rt_rule->rules[0];
2058 	rt_rule_entry->at_rear = true;
2059 
2060 	if(m_is_sta_mode != Q6_WAN)
2061 	{
2062 		IPACMDBG_H(" WAN instance is in STA mode \n");
2063 		for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
2064 		{
2065 			if(iptype != tx_prop->tx[tx_index].ip)
2066 			{
2067 				IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n",
2068 									tx_index, tx_prop->tx[tx_index].ip,iptype);
2069 				continue;
2070 			}
2071 
2072 			/* use the STA-header handler */
2073 			if (iptype == IPA_IP_v4)
2074 			{
2075 				strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name, sizeof(rt_rule->rt_tbl_name));
2076 				rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v4;
2077 			}
2078 			else
2079 			{
2080 				strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name));
2081 				rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v6;
2082 			}
2083 
2084 			IPACMDBG_H(" WAN table created %s \n", rt_rule->rt_tbl_name);
2085 			/* replace the hdr handle for q6_PCIE*/
2086 			if(m_is_sta_mode == Q6_MHI_WAN)
2087 			{
2088 				memset(&hdr, 0, sizeof(hdr));
2089 				strlcpy(hdr.name, tx_prop->tx[tx_index].hdr_name, sizeof(hdr.name));
2090 				hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
2091 				if(m_header.GetHeaderHandle(&hdr) == false)
2092 				{
2093 					IPACMERR("Failed to get QMAP header.\n");
2094 					free(rt_rule);
2095 					return IPACM_FAILURE;
2096 				}
2097 				rt_rule_entry->rule.hdr_hdl = hdr.hdl;
2098 				rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
2099 			}
2100 			else
2101 			{
2102 				if(IPACM_Iface::ipacmcfg->isMCC_Mode == true)
2103 				{
2104 					IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
2105 							tx_prop->tx[tx_index].alt_dst_pipe);
2106 					rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
2107 				}
2108 				else
2109 				{
2110 					rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
2111 				}
2112 			}
2113 			memcpy(&rt_rule_entry->rule.attrib,
2114 						 &tx_prop->tx[tx_index].attrib,
2115 						 sizeof(rt_rule_entry->rule.attrib));
2116 
2117 			rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
2118 			if (iptype == IPA_IP_v4)
2119 			{
2120 				rt_rule_entry->rule.attrib.u.v4.dst_addr      = 0;
2121 				rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0;
2122 				if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
2123 					rt_rule_entry->rule.hashable = true;
2124 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
2125 				/* use index hw-counter */
2126 				if((m_is_sta_mode == WLAN_WAN) && IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
2127 				{
2128 					IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_HW);
2129 					result = m_routing.AddRoutingRule_hw_index(rt_rule, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_HW);
2130 				} else {
2131 					result = m_routing.AddRoutingRule(rt_rule);
2132 				}
2133 #else
2134 				result = m_routing.AddRoutingRule(rt_rule);
2135 #endif
2136 				if (result == false)
2137 				{
2138 		    		IPACMERR("Routing rule addition failed!\n");
2139 		    		free(rt_rule);
2140 		    		return IPACM_FAILURE;
2141 				}
2142 				wan_route_rule_v4_hdl[tx_index] = rt_rule_entry->rt_rule_hdl;
2143 				IPACMDBG_H("Got ipv4 wan-route rule hdl:0x%x,tx:%d,ip-type: %d \n",
2144 							 wan_route_rule_v4_hdl[tx_index],
2145 							 tx_index,
2146 							 iptype);
2147 			}
2148 			else
2149 			{
2150 				rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0;
2151 				rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0;
2152 				rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0;
2153 				rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0;
2154 				rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0;
2155 				rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0;
2156 				rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0;
2157 				rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0;
2158 				if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
2159 					rt_rule_entry->rule.hashable = true;
2160 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
2161 				/* use index hw-counter */
2162 				if((m_is_sta_mode == WLAN_WAN) && IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
2163 				{
2164 					IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_HW);
2165 					result = m_routing.AddRoutingRule_hw_index(rt_rule, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_HW);
2166 				} else {
2167 					result = m_routing.AddRoutingRule(rt_rule);
2168 				}
2169 #else
2170 				result = m_routing.AddRoutingRule(rt_rule);
2171 #endif
2172 				if (result == false)
2173 				{
2174 		    		IPACMERR("Routing rule addition failed!\n");
2175 		    		free(rt_rule);
2176 		    		return IPACM_FAILURE;
2177 				}
2178 				wan_route_rule_v6_hdl[tx_index] = rt_rule_entry->rt_rule_hdl;
2179 				IPACMDBG_H("Set ipv6 wan-route rule hdl for v6_lan_table:0x%x,tx:%d,ip-type: %d \n",
2180 							 wan_route_rule_v6_hdl[tx_index],
2181 							 tx_index,
2182 							 iptype);
2183 			}
2184 		}
2185 	}
2186 
2187 	/* add a catch-all rule in wan dl routing table */
2188 
2189 	if (iptype == IPA_IP_v6 && m_is_sta_mode != Q6_MHI_WAN)
2190 	{
2191 		strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name));
2192 		IPACMDBG_H(" WAN table created %s \n", rt_rule->rt_tbl_name);
2193 		memset(rt_rule_entry, 0, sizeof(struct ipa_rt_rule_add));
2194 		rt_rule_entry->at_rear = true;
2195 		if(m_is_sta_mode == Q6_WAN)
2196 		{
2197 			memset(&hdr, 0, sizeof(hdr));
2198 			strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
2199 			hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
2200 			if(m_header.GetHeaderHandle(&hdr) == false)
2201 			{
2202 				IPACMERR("Failed to get QMAP header.\n");
2203 				free(rt_rule);
2204 				return IPACM_FAILURE;
2205 			}
2206 			rt_rule_entry->rule.hdr_hdl = hdr.hdl;
2207 			rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS;
2208 		}
2209 		else
2210 		{
2211 			/* create dummy ethernet header for v6 RX path */
2212 			IPACMDBG_H("Construct dummy ethernet_header\n");
2213 			if (add_dummy_rx_hdr())
2214 			{
2215 				IPACMERR("Construct dummy ethernet_header failed!\n");
2216 				free(rt_rule);
2217 				return IPACM_FAILURE;
2218 			}
2219 			rt_rule_entry->rule.hdr_proc_ctx_hdl = hdr_proc_hdl_dummy_v6;
2220 			rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS;
2221 		}
2222 		rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
2223 		rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0;
2224 		rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0;
2225 		rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0;
2226 		rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0;
2227 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0;
2228 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0;
2229 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0;
2230 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0;
2231 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
2232 			rt_rule_entry->rule.hashable = true;
2233 		if (false == m_routing.AddRoutingRule(rt_rule))
2234 		{
2235 			IPACMERR("Routing rule addition failed!\n");
2236 			free(rt_rule);
2237 			return IPACM_FAILURE;
2238 		}
2239 		wan_route_rule_v6_hdl_a5[0] = rt_rule_entry->rt_rule_hdl;
2240 		IPACMDBG_H("Set ipv6 wan-route rule hdl for v6_wan_table:0x%x,tx:%d,ip-type: %d \n",
2241 				wan_route_rule_v6_hdl_a5[0], 0, iptype);
2242 	}
2243 
2244 	/* support delete only, not post wan_down event */
2245 	if (add_only)
2246 	{
2247 		IPACMDBG_H(" Only add default WAN routing rules (%d)\n", add_only);
2248 		if(rt_rule != NULL)
2249 		{
2250 			free(rt_rule);
2251 		}
2252 		return IPACM_SUCCESS;
2253 	}
2254 
2255 	ipacm_event_iface_up *wanup_data;
2256 	wanup_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up));
2257 	if (wanup_data == NULL)
2258 	{
2259 		IPACMERR("Unable to allocate memory\n");
2260 		free(rt_rule);
2261 		return IPACM_FAILURE;
2262 	}
2263 	memset(wanup_data, 0, sizeof(ipacm_event_iface_up));
2264 
2265 	/* handling filter rule construction */
2266 	if (iptype == IPA_IP_v4)
2267 	{
2268 		/* set mtu_default_wan to current default wan instance */
2269 		mtu_default_wan_v4 = mtu_v4;
2270 		IPACMDBG_H("replace the mtu_wan to %d\n", mtu_default_wan_v4);
2271 
2272 		IPACM_Wan::wan_up = true;
2273 		active_v4 = true;
2274 		memcpy(IPACM_Wan::wan_up_dev_name,
2275 			dev_name,
2276 				sizeof(IPACM_Wan::wan_up_dev_name));
2277 
2278 		if(m_is_sta_mode == Q6_WAN)
2279 		{
2280 			config_wan_firewall_rule(IPA_IP_v4);
2281 			install_wan_filtering_rule(false);
2282 		}
2283 		else
2284 		{
2285 			config_dft_firewall_rules(IPA_IP_v4);
2286 		}
2287 
2288 		memcpy(wanup_data->ifname, dev_name, sizeof(wanup_data->ifname));
2289 		wanup_data->ipv4_addr = wan_v4_addr;
2290 		wanup_data->backhaul_type = m_is_sta_mode;
2291 		IPACMDBG_H("Posting IPA_HANDLE_WAN_UP with below information:\n");
2292 		IPACMDBG_H("if_name:%s, ipv4_address:0x%x, is sta mode:%d\n",
2293 				wanup_data->ifname, wanup_data->ipv4_addr, wanup_data->backhaul_type);
2294 		memset(&evt_data, 0, sizeof(evt_data));
2295 
2296 		/* set backhaul type as xlat */
2297 		IPACM_Wan::is_xlat = is_xlat_local;
2298 
2299 		/* send xlat configuration for installing uplink rules */
2300 		if(is_xlat_local && (m_is_sta_mode == Q6_WAN))
2301 		{
2302 			IPACM_Wan::xlat_mux_id = ext_prop->ext[0].mux_id;
2303 			wanup_data->xlat_mux_id = IPACM_Wan::xlat_mux_id;
2304 			IPACMDBG_H("Set xlat configuraiton with below information:\n");
2305 			IPACMDBG_H("xlat_enabled: %d set xlat_mux_id: %d \n",
2306 					is_xlat_local, IPACM_Wan::xlat_mux_id);
2307 		}
2308 		else /*temp put xlat = 0 for Q6_MHI_WAN*/
2309 		{
2310 			IPACM_Wan::xlat_mux_id = 0;
2311 			wanup_data->xlat_mux_id = 0;
2312 			if(m_is_sta_mode != WLAN_WAN) //both q6_wan/q6_mhi_wan
2313 			{
2314 				wanup_data->mux_id = ext_prop->ext[0].mux_id;
2315 				IPACMDBG_H("mux_id: %d\n", wanup_data->mux_id);
2316 			}
2317 			else
2318 				wanup_data->mux_id = 0;
2319 			IPACMDBG_H("No xlat configuration\n");
2320 		}
2321 		evt_data.event = IPA_HANDLE_WAN_UP;
2322 		evt_data.evt_data = (void *)wanup_data;
2323 		IPACM_EvtDispatcher::PostEvt(&evt_data);
2324 
2325 #ifdef FEATURE_IPACM_HAL
2326 		post_wan_up_tether_evt(IPA_IP_v4, 0);
2327 #endif
2328 	}
2329 	else
2330 	{
2331 		/* set mtu_default_wan to current default wan instance */
2332 		mtu_default_wan_v6 = mtu_v6;
2333 		IPACMDBG_H("replace the mtu_wan to %d\n", mtu_default_wan_v6);
2334 
2335 		memcpy(backhaul_ipv6_prefix, ipv6_prefix, sizeof(backhaul_ipv6_prefix));
2336 		IPACMDBG_H("Setup backhaul ipv6 prefix to be 0x%08x%08x.\n", backhaul_ipv6_prefix[0], backhaul_ipv6_prefix[1]);
2337 
2338 		IPACM_Wan::wan_up_v6 = true;
2339 		active_v6 = true;
2340 		memcpy(IPACM_Wan::wan_up_dev_name,
2341 			dev_name,
2342 				sizeof(IPACM_Wan::wan_up_dev_name));
2343 
2344 		if(m_is_sta_mode == Q6_WAN)
2345 		{
2346 			config_wan_firewall_rule(IPA_IP_v6);
2347 			install_wan_filtering_rule(false);
2348 		}
2349 		else
2350 		{
2351 			config_dft_firewall_rules(IPA_IP_v6);
2352 		}
2353 
2354 		memcpy(wanup_data->ifname, dev_name, sizeof(wanup_data->ifname));
2355 		wanup_data->backhaul_type = m_is_sta_mode;
2356 		memcpy(wanup_data->ipv6_prefix, ipv6_prefix, sizeof(wanup_data->ipv6_prefix));
2357 		IPACMDBG_H("Posting IPA_HANDLE_WAN_UP_V6 with below information:\n");
2358 		IPACMDBG_H("if_name:%s, is sta mode: %d\n", wanup_data->ifname, wanup_data->backhaul_type);
2359 		IPACMDBG_H("ipv6 prefix: 0x%08x%08x.\n", ipv6_prefix[0], ipv6_prefix[1]);
2360 		memset(&evt_data, 0, sizeof(evt_data));
2361 		evt_data.event = IPA_HANDLE_WAN_UP_V6;
2362 		evt_data.evt_data = (void *)wanup_data;
2363 		IPACM_EvtDispatcher::PostEvt(&evt_data);
2364 
2365 #ifdef FEATURE_IPACM_HAL
2366                 post_wan_up_tether_evt(IPA_IP_v6, 0);
2367 #endif
2368 	}
2369 
2370 	if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_None && IPACM_Iface::ipacmcfg->GetIPAVer() < IPA_HW_v4_0)
2371 	{
2372 			/* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */
2373 			IPACMDBG_H("dev %s add producer dependency\n", dev_name);
2374 			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]);
2375 			IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false);
2376 	}
2377 #ifdef WAN_IOC_NOTIFY_WAN_STATE
2378 	else {
2379 			if ((m_is_sta_mode == Q6_WAN && ipa_pm_q6_check == 0 ) || (m_is_sta_mode == Q6_MHI_WAN))
2380 			{
2381 				fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
2382 				if(fd_wwan_ioctl < 0)
2383 				{
2384 					IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME);
2385 					free(rt_rule);
2386 					return false;
2387 				}
2388 				IPACMDBG_H("send WAN_IOC_NOTIFY_WAN_STATE up to IPA_PM\n");
2389 				wan_state.up = true;
2390 #ifdef WAN_IOCTL_NOTIFY_WAN_INTF_NAME
2391 				strlcpy(wan_state.upstreamIface, dev_name, IFNAMSIZ);
2392 #endif
2393 				if(ioctl(fd_wwan_ioctl, WAN_IOC_NOTIFY_WAN_STATE, &wan_state))
2394 				{
2395 					IPACMERR("Failed to send WAN_IOC_NOTIFY_WAN_STATE as up %d\n ", wan_state.up);
2396 				}
2397 				close(fd_wwan_ioctl);
2398 
2399 				/* Store the Offload state. */
2400 				FILE *fp = NULL;
2401 				fp = fopen(IPA_OFFLOAD_TETHER_STATE_FILE_NAME, "w");
2402 				if (fp == NULL)
2403 				{
2404 					IPACMERR("Failed to write offload state to %s, error is %d - %s\n",
2405 						IPA_OFFLOAD_TETHER_STATE_FILE_NAME, errno, strerror(errno));
2406 				}
2407 				else
2408 				{
2409 					fprintf(fp, "UPSTREAM=%s,STATE=UP", dev_name);
2410 					fclose(fp);
2411 				}
2412 			}
2413 			ipa_pm_q6_check++;
2414 			IPACMDBG_H("update ipa_pm_q6_check to %d\n", ipa_pm_q6_check);
2415 	}
2416 #endif
2417 
2418 	if(rt_rule != NULL)
2419 	{
2420 		free(rt_rule);
2421 	}
2422 	return IPACM_SUCCESS;
2423 }
2424 
2425 #ifdef FEATURE_IPA_ANDROID
2426 /* wan default route/filter rule configuration */
post_wan_up_tether_evt(ipa_ip_type iptype,int ipa_if_num_tether)2427 int IPACM_Wan::post_wan_up_tether_evt(ipa_ip_type iptype, int ipa_if_num_tether)
2428 {
2429 	ipacm_cmd_q_data evt_data;
2430 	ipacm_event_iface_up_tehter *wanup_data;
2431 
2432 	wanup_data = (ipacm_event_iface_up_tehter *)malloc(sizeof(ipacm_event_iface_up_tehter));
2433 	if (wanup_data == NULL)
2434 	{
2435 		IPACMERR("Unable to allocate memory\n");
2436 		return IPACM_FAILURE;
2437 	}
2438 	memset(wanup_data, 0, sizeof(ipacm_event_iface_up_tehter));
2439 
2440 	wanup_data->if_index_tether = ipa_if_num_tether;
2441 	wanup_data->backhaul_type = m_is_sta_mode;
2442 	/* xlat mux-id*/
2443 	if(is_xlat_local && (m_is_sta_mode == Q6_WAN))
2444 		wanup_data->xlat_mux_id = ext_prop->ext[0].mux_id;
2445 	else
2446 		wanup_data->xlat_mux_id = 0;
2447 	IPACMDBG_H("Posting IPA_HANDLE_WAN_UP_TETHER with below information:\n");
2448 	IPACMDBG_H("tether_if_name:%s, is sta mode:%d xlat_mux_id: %d\n",
2449 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, wanup_data->backhaul_type, wanup_data->xlat_mux_id);
2450 
2451 	memset(&evt_data, 0, sizeof(evt_data));
2452 
2453 	if (iptype == IPA_IP_v4)
2454 	{
2455 		evt_data.event = IPA_HANDLE_WAN_UP_TETHER;
2456 #ifndef FEATURE_IPACM_HAL
2457 		/* Add support tether ifaces to its array*/
2458 		IPACM_Wan::ipa_if_num_tether_v4[IPACM_Wan::ipa_if_num_tether_v4_total] = ipa_if_num_tether;
2459 		IPACMDBG_H("adding tether iface(%s) ipa_if_num_tether_v4_total(%d) on wan_iface(%s)\n",
2460 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name,
2461 			IPACM_Wan::ipa_if_num_tether_v4_total,
2462 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name);
2463 		IPACM_Wan::ipa_if_num_tether_v4_total++;
2464 #endif
2465 	}
2466 	else
2467 	{
2468 		evt_data.event = IPA_HANDLE_WAN_UP_V6_TETHER;
2469 		memcpy(wanup_data->ipv6_prefix, ipv6_prefix, sizeof(wanup_data->ipv6_prefix));
2470 #ifndef FEATURE_IPACM_HAL
2471 		/* Add support tether ifaces to its array*/
2472 		IPACM_Wan::ipa_if_num_tether_v6[IPACM_Wan::ipa_if_num_tether_v6_total] = ipa_if_num_tether;
2473 		IPACMDBG_H("adding tether iface(%s) ipa_if_num_tether_v6_total(%d) on wan_iface(%s)\n",
2474 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name,
2475 			IPACM_Wan::ipa_if_num_tether_v6_total,
2476 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name);
2477 		IPACM_Wan::ipa_if_num_tether_v6_total++;
2478 #endif
2479 	}
2480 		evt_data.evt_data = (void *)wanup_data;
2481 		IPACM_EvtDispatcher::PostEvt(&evt_data);
2482 
2483 	return IPACM_SUCCESS;
2484 }
2485 
2486 
2487 /* wan default route/filter rule configuration */
post_wan_down_tether_evt(ipa_ip_type iptype,int ipa_if_num_tether)2488 int IPACM_Wan::post_wan_down_tether_evt(ipa_ip_type iptype, int ipa_if_num_tether)
2489 {
2490 	ipacm_cmd_q_data evt_data;
2491 	ipacm_event_iface_up_tehter *wandown_data;
2492 
2493 	wandown_data = (ipacm_event_iface_up_tehter *)malloc(sizeof(ipacm_event_iface_up_tehter));
2494 	if (wandown_data == NULL)
2495 	{
2496 		IPACMERR("Unable to allocate memory\n");
2497 		return IPACM_FAILURE;
2498 	}
2499 	memset(wandown_data, 0, sizeof(ipacm_event_iface_up_tehter));
2500 
2501 	wandown_data->if_index_tether = ipa_if_num_tether;
2502 	wandown_data->backhaul_type = m_is_sta_mode;
2503 	IPACMDBG_H("Posting IPA_HANDLE_WAN_DOWN_TETHER with below information:\n");
2504 	IPACMDBG_H("tether_if_name:%s, is sta mode:%d\n",
2505 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, wandown_data->backhaul_type);
2506 	memset(&evt_data, 0, sizeof(evt_data));
2507 
2508 	if (iptype == IPA_IP_v4)
2509 	{
2510 #ifndef FEATURE_IPACM_HAL
2511 		if(delete_tether_iface(iptype, ipa_if_num_tether))
2512 		{
2513 			IPACMDBG_H("Not finding the tethered client on ipv4.\n");
2514 			free(wandown_data);
2515 			return IPACM_SUCCESS;
2516 		}
2517 #endif
2518 		evt_data.event = IPA_HANDLE_WAN_DOWN_TETHER;
2519 	}
2520 	else
2521 	{
2522 #ifndef FEATURE_IPACM_HAL
2523 		if(delete_tether_iface(iptype, ipa_if_num_tether))
2524 		{
2525 			IPACMDBG_H("Not finding the tethered client on ipv6.\n");
2526 			free(wandown_data);
2527 			return IPACM_SUCCESS;
2528 		}
2529 #endif
2530 		evt_data.event = IPA_HANDLE_WAN_DOWN_V6_TETHER;
2531 	}
2532 		evt_data.evt_data = (void *)wandown_data;
2533 		IPACM_EvtDispatcher::PostEvt(&evt_data);
2534 	return IPACM_SUCCESS;
2535 }
2536 #endif
2537 
2538 /* construct complete ethernet header */
handle_sta_header_add_evt(bool renew)2539 int IPACM_Wan::handle_sta_header_add_evt(bool renew)
2540 {
2541 	int res = IPACM_SUCCESS, index = IPACM_INVALID_INDEX;
2542 	if((header_set_v4 == true) || (header_set_v6 == true))
2543 	{
2544 		IPACMDBG_H("Already add STA full header\n");
2545 		return IPACM_SUCCESS;
2546 	}
2547 
2548 	/* checking if the ipv4 same as default route */
2549 	if(wan_v4_addr_gw_set)
2550 	{
2551 		index = get_wan_client_index_ipv4(wan_v4_addr_gw);
2552 		if (index != IPACM_INVALID_INDEX)
2553 		{
2554 			IPACMDBG_H("Matched client index: %d\n", index);
2555 			IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
2556 					 get_client_memptr(wan_client, index)->mac[0],
2557 					 get_client_memptr(wan_client, index)->mac[1],
2558 					 get_client_memptr(wan_client, index)->mac[2],
2559 					 get_client_memptr(wan_client, index)->mac[3],
2560 					 get_client_memptr(wan_client, index)->mac[4],
2561 					 get_client_memptr(wan_client, index)->mac[5]);
2562 
2563 			if(get_client_memptr(wan_client, index)->ipv4_header_set)
2564 			{
2565 				hdr_hdl_sta_v4 = get_client_memptr(wan_client, index)->hdr_hdl_v4;
2566 				header_set_v4 = true;
2567 				IPACMDBG_H("add full ipv4 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v4);
2568 				/* store external_ap's MAC */
2569 				memcpy(ext_router_mac_addr, get_client_memptr(wan_client, index)->mac, sizeof(ext_router_mac_addr));
2570 			}
2571 			else
2572 			{
2573 				IPACMERR(" wan-client got ipv4 however didn't construct complete ipv4 header \n");
2574 				return IPACM_FAILURE;
2575 			}
2576 
2577 			if(get_client_memptr(wan_client, index)->ipv6_header_set)
2578 			{
2579 				hdr_hdl_sta_v6 = get_client_memptr(wan_client, index)->hdr_hdl_v6;
2580 				header_set_v6 = true;
2581 				IPACMDBG_H("add full ipv6 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v6);
2582 			}
2583 			else
2584 			{
2585 				IPACMERR(" wan-client got ipv6 however didn't construct complete ipv6 header \n");
2586 				return IPACM_FAILURE;
2587 			}
2588 		}
2589 		else
2590 		{
2591 			IPACMDBG_H(" currently can't find matched wan-client's MAC-addr, waiting for header construction\n");
2592 			return IPACM_SUCCESS;
2593 		}
2594 	}
2595 
2596 	/* see if v4 default routes are setup before constructing full header */
2597 	if(header_partial_default_wan_v4 == true)
2598 	{
2599 	   handle_route_add_evt(IPA_IP_v4, renew);
2600 	}
2601 
2602 	/* checking if the ipv6 same as default route */
2603 	if(wan_v6_addr_gw_set)
2604 	{
2605 		index = get_wan_client_index_ipv6(wan_v6_addr_gw);
2606 		if (index != IPACM_INVALID_INDEX)
2607 		{
2608 			IPACMDBG_H("Matched client index: %d\n", index);
2609 			IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
2610 					 get_client_memptr(wan_client, index)->mac[0],
2611 					 get_client_memptr(wan_client, index)->mac[1],
2612 					 get_client_memptr(wan_client, index)->mac[2],
2613 					 get_client_memptr(wan_client, index)->mac[3],
2614 					 get_client_memptr(wan_client, index)->mac[4],
2615 					 get_client_memptr(wan_client, index)->mac[5]);
2616 
2617 			if(get_client_memptr(wan_client, index)->ipv6_header_set)
2618 			{
2619 				hdr_hdl_sta_v6 = get_client_memptr(wan_client, index)->hdr_hdl_v6;
2620 				header_set_v6 = true;
2621 				IPACMDBG_H("add full ipv6 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v6);
2622 				/* store external_ap's MAC */
2623 				memcpy(ext_router_mac_addr, get_client_memptr(wan_client, index)->mac, sizeof(ext_router_mac_addr));
2624 			}
2625 			else
2626 			{
2627 				IPACMERR(" wan-client got ipv6 however didn't construct complete ipv4 header \n");
2628 				return IPACM_FAILURE;
2629 			}
2630 
2631 			if(get_client_memptr(wan_client, index)->ipv4_header_set)
2632 			{
2633 				hdr_hdl_sta_v4 = get_client_memptr(wan_client, index)->hdr_hdl_v4;
2634 				header_set_v4 = true;
2635 				IPACMDBG_H("add full ipv4 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v4);
2636 			}
2637 			else
2638 			{
2639 				IPACMERR(" wan-client got ipv4 however didn't construct complete ipv4 header \n");
2640 				return IPACM_FAILURE;
2641 			}
2642 		}
2643 		else
2644 		{
2645 			IPACMDBG_H(" currently can't find matched wan-client's MAC-addr, waiting for header construction\n");
2646 			return IPACM_SUCCESS;
2647 		}
2648 	}
2649 
2650 	/* see if v6 default routes are setup before constructing full header */
2651 
2652 	if(header_partial_default_wan_v6 == true)
2653 	{
2654 	   handle_route_add_evt(IPA_IP_v6, renew);
2655 	}
2656 	return res;
2657 }
2658 
2659 /* For checking attribute mask field in firewall rules for IPv6 only */
check_dft_firewall_rules_attr_mask(IPACM_firewall_conf_t * firewall_config)2660 bool IPACM_Wan::check_dft_firewall_rules_attr_mask(IPACM_firewall_conf_t *firewall_config)
2661 {
2662 	uint32_t attrib_mask = 0ul;
2663 	attrib_mask =	IPA_FLT_SRC_PORT_RANGE |
2664 			IPA_FLT_DST_PORT_RANGE |
2665 			IPA_FLT_TYPE |
2666 			IPA_FLT_CODE |
2667 			IPA_FLT_SPI |
2668 			IPA_FLT_SRC_PORT |
2669 			IPA_FLT_DST_PORT;
2670 
2671 	for (int i = 0; i < firewall_config->num_extd_firewall_entries; i++)
2672 	{
2673 		if (firewall_config->extd_firewall_entries[i].ip_vsn == 6)
2674 		{
2675 			if (firewall_config->extd_firewall_entries[i].attrib.attrib_mask & attrib_mask)
2676 			{
2677 				IPACMDBG_H("IHL based attribute mask is found: install IPv6 frag firewall rule \n");
2678 				return true;
2679 			}
2680 		}
2681 	}
2682 	IPACMDBG_H("IHL based attribute mask is not found: no IPv6 frag firewall rule \n");
2683 	return false;
2684 }
2685 
2686 /* for STA mode: add firewall rules */
config_dft_firewall_rules(ipa_ip_type iptype)2687 int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype)
2688 {
2689 	struct ipa_flt_rule_add flt_rule_entry;
2690 	int i, rule_v4 = 0, rule_v6 = 0, len;
2691 	bool result;
2692 
2693 	IPACMDBG_H("ip-family: %d; \n", iptype);
2694 
2695 	if (rx_prop == NULL)
2696 	{
2697 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
2698 		return IPACM_SUCCESS;
2699 	}
2700 
2701 	/* default firewall is disable and the rule action is drop */
2702 	memset(&firewall_config, 0, sizeof(firewall_config));
2703 	strlcpy(firewall_config.firewall_config_file, "/etc/mobileap_firewall.xml", sizeof(firewall_config.firewall_config_file));
2704 
2705 	if(m_is_sta_mode != Q6_MHI_WAN)
2706 	{
2707 		IPACMDBG_H("Firewall XML file is %s \n", firewall_config.firewall_config_file);
2708 		if (IPACM_SUCCESS == IPACM_read_firewall_xml(firewall_config.firewall_config_file, &firewall_config))
2709 		{
2710 			IPACMDBG_H("QCMAP Firewall XML read OK \n");
2711 			/* find the number of v4/v6 firewall rules */
2712 			for (i = 0; i < firewall_config.num_extd_firewall_entries; i++)
2713 			{
2714 				if (firewall_config.extd_firewall_entries[i].ip_vsn == 4)
2715 				{
2716 					rule_v4++;
2717 				}
2718 				else
2719 				{
2720 					rule_v6++;
2721 				}
2722 			}
2723 			IPACMDBG_H("firewall rule v4:%d v6:%d total:%d\n", rule_v4, rule_v6, firewall_config.num_extd_firewall_entries);
2724 		}
2725 		else
2726 		{
2727 			IPACMERR("QCMAP Firewall XML read failed, no that file, use default configuration \n");
2728 		}
2729 	}
2730 	else
2731 	{
2732 		IPACMDBG_H("in Q6_MHI_WAN mode, skip firewall, use default configuration \n");
2733 	}
2734 	/* construct ipa_ioc_add_flt_rule with N firewall rules */
2735 	ipa_ioc_add_flt_rule *m_pFilteringTable = NULL;
2736 	len = sizeof(struct ipa_ioc_add_flt_rule) + 1 * sizeof(struct ipa_flt_rule_add);
2737 	m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
2738 	if (!m_pFilteringTable)
2739 	{
2740 		IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
2741 		return IPACM_FAILURE;
2742 	}
2743 
2744 	if(iptype == IPA_IP_v6 &&
2745 			firewall_config.firewall_enable == true &&
2746 			check_dft_firewall_rules_attr_mask(&firewall_config))
2747 	{
2748 		m_pFilteringTable->commit = 1;
2749 		m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
2750 		m_pFilteringTable->global = false;
2751 		m_pFilteringTable->ip = IPA_IP_v6;
2752 		m_pFilteringTable->num_rules = (uint8_t)1;
2753 
2754 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
2755 		flt_rule_entry.at_rear = true;
2756 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
2757 		{
2758 			flt_rule_entry.at_rear = false;
2759 			flt_rule_entry.rule.hashable = false;
2760 		}
2761 		flt_rule_entry.flt_rule_hdl = -1;
2762 		flt_rule_entry.status = -1;
2763 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
2764 		memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(struct ipa_rule_attrib));
2765 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
2766 		memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
2767 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
2768 		/* use index hw-counter */
2769 		if(IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
2770 		{
2771 			IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
2772 			result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL);
2773 		} else {
2774 			result = m_filtering.AddFilteringRule(m_pFilteringTable);
2775 		}
2776 #else
2777 		result = m_filtering.AddFilteringRule(m_pFilteringTable);
2778 #endif
2779 		if (false == result)
2780 		{
2781 			IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
2782 			free(m_pFilteringTable);
2783 			return IPACM_FAILURE;
2784 		}
2785 		else
2786 		{
2787 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
2788 			ipv6_frag_firewall_flt_rule_hdl = m_pFilteringTable->rules[0].flt_rule_hdl;
2789 			is_ipv6_frag_firewall_flt_rule_installed = true;
2790 			IPACMDBG_H("Installed IPv6 frag firewall rule, handle %d.\n", ipv6_frag_firewall_flt_rule_hdl);
2791 		}
2792 	}
2793 
2794 	if (iptype == IPA_IP_v4)
2795 	{
2796 		if (rule_v4 == 0)
2797 		{
2798 			memset(m_pFilteringTable, 0, len);
2799 
2800 			m_pFilteringTable->commit = 1;
2801 			m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
2802 			m_pFilteringTable->global = false;
2803 			m_pFilteringTable->ip = IPA_IP_v4;
2804 			m_pFilteringTable->num_rules = (uint8_t)1;
2805 
2806 			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
2807 
2808 			if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4))
2809 			{
2810 				IPACMERR("m_routing.GetRoutingTable(rt_tbl_lan_v4) Failed.\n");
2811 				free(m_pFilteringTable);
2812 				return IPACM_FAILURE;
2813 			}
2814 
2815 			flt_rule_entry.flt_rule_hdl = -1;
2816 			flt_rule_entry.status = -1;
2817 
2818 			/* firewall disable, all traffic are allowed */
2819 			if(firewall_config.firewall_enable == true)
2820 			{
2821 				flt_rule_entry.at_rear = true;
2822 
2823 				/* default action for v4 is go DST_NAT unless user set to exception*/
2824 				if(firewall_config.rule_action_accept == true)
2825 				{
2826 					flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
2827 				}
2828 				else
2829 				{
2830 					if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
2831 					{
2832 						flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
2833 					}
2834 					else
2835 					{
2836 						flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
2837 					}
2838 				}
2839 			}
2840 			else
2841 			{
2842 				flt_rule_entry.at_rear = true;
2843 				if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
2844 				{
2845 					flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
2846 				}
2847 				else
2848 				{
2849 					flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
2850 				}
2851             }
2852 			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
2853 			{
2854 				flt_rule_entry.at_rear = true;
2855 				flt_rule_entry.rule.hashable = true;
2856 			}
2857 			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
2858 			memcpy(&flt_rule_entry.rule.attrib,
2859 						 &rx_prop->rx[0].attrib,
2860 						 sizeof(struct ipa_rule_attrib));
2861 			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
2862 			flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000;
2863 			flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000;
2864 
2865 			/* disble meta-data filtering */
2866 			if(m_is_sta_mode == Q6_MHI_WAN)
2867 			{
2868 				flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA);
2869 				IPACMDBG_H("disable meta-data filtering 0x%x\n", flt_rule_entry.rule.attrib.attrib_mask);
2870 			}
2871 
2872 			memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
2873 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
2874 			/* use index hw-counter */
2875 			if(IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
2876 			{
2877 				IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
2878 				result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL);
2879 			} else {
2880 				result = m_filtering.AddFilteringRule(m_pFilteringTable);
2881 			}
2882 #else
2883 			result = m_filtering.AddFilteringRule(m_pFilteringTable);
2884 #endif
2885 			if (false == result)
2886 			{
2887 				IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
2888 				free(m_pFilteringTable);
2889 				return IPACM_FAILURE;
2890 			}
2891 			else
2892 			{
2893 				IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
2894 				IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
2895 			}
2896 
2897 			/* copy filter hdls */
2898 			dft_wan_fl_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl;
2899 		}
2900 		else
2901 		{
2902 			memset(m_pFilteringTable, 0, len);
2903 
2904 			m_pFilteringTable->commit = 1;
2905 			m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
2906 			m_pFilteringTable->global = false;
2907 			m_pFilteringTable->ip = IPA_IP_v4;
2908 			m_pFilteringTable->num_rules = (uint8_t)1;
2909 
2910 			IPACMDBG_H("Retreiving Routing handle for routing table name:%s\n",
2911 							 IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name);
2912 			if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4))
2913 			{
2914 				IPACMERR("m_routing.GetRoutingTable(&rt_tbl_lan_v4=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_lan_v4);
2915 				free(m_pFilteringTable);
2916 				return IPACM_FAILURE;
2917 			}
2918 			IPACMDBG_H("Routing handle for wan routing table:0x%x\n", IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl);
2919 
2920             if(firewall_config.firewall_enable == true)
2921             {
2922 			rule_v4 = 0;
2923 			for (i = 0; i < firewall_config.num_extd_firewall_entries; i++)
2924 			{
2925 				if (firewall_config.extd_firewall_entries[i].ip_vsn == 4)
2926 				{
2927 					memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
2928 
2929 		    			flt_rule_entry.at_rear = true;
2930 					flt_rule_entry.flt_rule_hdl = -1;
2931 					flt_rule_entry.status = -1;
2932 					flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
2933 
2934 					/* Accept v4 matched rules*/
2935                     if(firewall_config.rule_action_accept == true)
2936 			        {
2937 						if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
2938 						{
2939 							flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
2940 						}
2941 						else
2942 						{
2943 							flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
2944 						}
2945 			        }
2946 			        else
2947 			        {
2948 			            flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
2949                     }
2950 					if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
2951 						flt_rule_entry.rule.hashable = true;
2952 					memcpy(&flt_rule_entry.rule.attrib,
2953 								 &firewall_config.extd_firewall_entries[i].attrib,
2954 								 sizeof(struct ipa_rule_attrib));
2955 
2956 					IPACMDBG_H("rx property attrib mask: 0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
2957 					flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask;
2958 					flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask;
2959 					flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data;
2960 
2961 					/* check if the rule is define as TCP_UDP, split into 2 rules, 1 for TCP and 1 UDP */
2962 					if (firewall_config.extd_firewall_entries[i].attrib.u.v4.protocol
2963 							== IPACM_FIREWALL_IPPROTO_TCP_UDP)
2964 					{
2965 						/* insert TCP rule*/
2966 						flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_TCP;
2967 						memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
2968 
2969 						IPACMDBG_H("Filter rule attrib mask: 0x%x\n",
2970 										 m_pFilteringTable->rules[0].rule.attrib.attrib_mask);
2971 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
2972 						/* use index hw-counter */
2973 						if(IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
2974 						{
2975 							IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
2976 							result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL);
2977 						} else {
2978 							result = m_filtering.AddFilteringRule(m_pFilteringTable);
2979 						}
2980 #else
2981 						result = m_filtering.AddFilteringRule(m_pFilteringTable);
2982 #endif
2983 
2984 						if (false == result)
2985 						{
2986 							IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
2987 							free(m_pFilteringTable);
2988 							return IPACM_FAILURE;
2989 						}
2990 						else
2991 						{
2992 							IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
2993 							/* save v4 firewall filter rule handler */
2994 							IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n",
2995 											 m_pFilteringTable->rules[rule_v4].flt_rule_hdl,
2996 											 m_pFilteringTable->rules[rule_v4].status);
2997 							firewall_hdl_v4[rule_v4] = m_pFilteringTable->rules[0].flt_rule_hdl;
2998 							num_firewall_v4++;
2999 							rule_v4++;
3000 						}
3001 
3002 						/* insert UDP rule*/
3003 						flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_UDP;
3004 						memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3005 
3006 						IPACMDBG_H("Filter rule attrib mask: 0x%x\n",
3007 										 m_pFilteringTable->rules[0].rule.attrib.attrib_mask);
3008 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
3009 						/* use index hw-counter */
3010 						if(IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
3011 						{
3012 							IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
3013 							result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL);
3014 						} else {
3015 							result = m_filtering.AddFilteringRule(m_pFilteringTable);
3016 						}
3017 #else
3018 						result = m_filtering.AddFilteringRule(m_pFilteringTable);
3019 #endif
3020 
3021 						if (false == result)
3022 						{
3023 							IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
3024 							free(m_pFilteringTable);
3025 							return IPACM_FAILURE;
3026 						}
3027 						else
3028 						{
3029 							IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
3030 							/* save v4 firewall filter rule handler */
3031 							IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n",
3032 											 m_pFilteringTable->rules[rule_v4].flt_rule_hdl,
3033 											 m_pFilteringTable->rules[rule_v4].status);
3034 							firewall_hdl_v4[rule_v4] = m_pFilteringTable->rules[0].flt_rule_hdl;
3035 							num_firewall_v4++;
3036 							rule_v4++;
3037 						}
3038 					}
3039 					else
3040 					{
3041 						memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3042 
3043 						IPACMDBG_H("Filter rule attrib mask: 0x%x\n",
3044 										 m_pFilteringTable->rules[0].rule.attrib.attrib_mask);
3045 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
3046 						/* use index hw-counter */
3047 						if(IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
3048 						{
3049 							IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
3050 							result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL);
3051 						} else {
3052 							result = m_filtering.AddFilteringRule(m_pFilteringTable);
3053 						}
3054 #else
3055 						result = m_filtering.AddFilteringRule(m_pFilteringTable);
3056 #endif
3057 
3058 						if (false == result)
3059 						{
3060 							IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
3061 							free(m_pFilteringTable);
3062 							return IPACM_FAILURE;
3063 						}
3064 						else
3065 						{
3066 							IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
3067 							/* save v4 firewall filter rule handler */
3068 							IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n",
3069 											 m_pFilteringTable->rules[rule_v4].flt_rule_hdl,
3070 											 m_pFilteringTable->rules[rule_v4].status);
3071 							firewall_hdl_v4[rule_v4] = m_pFilteringTable->rules[0].flt_rule_hdl;
3072 							num_firewall_v4++;
3073 							rule_v4++;
3074 						}
3075 					}
3076 				}
3077 			} /* end of firewall ipv4 filter rule add for loop*/
3078             }
3079 			/* configure default filter rule */
3080 			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
3081 
3082 			flt_rule_entry.flt_rule_hdl = -1;
3083 			flt_rule_entry.status = -1;
3084 
3085 			/* firewall disable, all traffic are allowed */
3086             if(firewall_config.firewall_enable == true)
3087 			{
3088 			     flt_rule_entry.at_rear = true;
3089 
3090 			     /* default action for v4 is go DST_NAT unless user set to exception*/
3091                              if(firewall_config.rule_action_accept == true)
3092 			     {
3093 			        flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
3094 			     }
3095 			     else
3096 			     {
3097 					if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
3098 					{
3099 						flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
3100 					}
3101 					else
3102 					{
3103 						flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
3104 					}
3105 				}
3106 		    }
3107 			else
3108 			{
3109 			    flt_rule_entry.at_rear = true;
3110 				if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER)
3111 				{
3112 					flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
3113 				}
3114 				else
3115 				{
3116 					flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
3117 				}
3118             }
3119 			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
3120 				flt_rule_entry.rule.hashable = true;
3121 			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
3122 			memcpy(&flt_rule_entry.rule.attrib,
3123 						 &rx_prop->rx[0].attrib,
3124 						 sizeof(struct ipa_rule_attrib));
3125 			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
3126 			flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000;
3127 			flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000;
3128 
3129 			memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3130 
3131 			IPACMDBG_H("Filter rule attrib mask: 0x%x\n",
3132 							 m_pFilteringTable->rules[0].rule.attrib.attrib_mask);
3133 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
3134 			/* use index hw-counter */
3135 			if(IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
3136 			{
3137 				IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
3138 				result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL);
3139 			} else {
3140 				result = m_filtering.AddFilteringRule(m_pFilteringTable);
3141 			}
3142 #else
3143 			result = m_filtering.AddFilteringRule(m_pFilteringTable);
3144 #endif
3145 
3146 			if (false == result)
3147 			{
3148 				IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
3149 				free(m_pFilteringTable);
3150 				return IPACM_FAILURE;
3151 			}
3152 			else
3153 			{
3154 				IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
3155 				IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
3156 			}
3157 
3158 			/* copy filter hdls */
3159 			dft_wan_fl_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl;
3160 		}
3161 
3162 	}
3163 	else
3164 	{
3165 		if (rule_v6 == 0)
3166 		{
3167 			memset(m_pFilteringTable, 0, len);
3168 
3169 			m_pFilteringTable->commit = 1;
3170 			m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
3171 			m_pFilteringTable->global = false;
3172 			m_pFilteringTable->ip = IPA_IP_v6;
3173 			m_pFilteringTable->num_rules = (uint8_t)1;
3174 
3175 			if(m_is_sta_mode != Q6_MHI_WAN)
3176 			{
3177 				/* Construct ICMP rule */
3178 				memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
3179 				flt_rule_entry.at_rear = true;
3180 				flt_rule_entry.flt_rule_hdl = -1;
3181 				flt_rule_entry.status = -1;
3182 				flt_rule_entry.rule.retain_hdr = 1;
3183 				flt_rule_entry.rule.eq_attrib_type = 0;
3184 				flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
3185 				if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
3186 					flt_rule_entry.rule.hashable = true;
3187 				memcpy(&flt_rule_entry.rule.attrib,
3188 						&rx_prop->rx[0].attrib,
3189 						sizeof(struct ipa_rule_attrib));
3190 				flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
3191 				flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6;
3192 				memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3193 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
3194 			/* use index hw-counter */
3195 			if(IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
3196 			{
3197 				IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
3198 				result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL);
3199 			} else {
3200 				result = m_filtering.AddFilteringRule(m_pFilteringTable);
3201 			}
3202 #else
3203 			result = m_filtering.AddFilteringRule(m_pFilteringTable);
3204 #endif
3205 
3206 			if (false == result)
3207 				{
3208 					IPACMERR("Error Adding Filtering rules, aborting...\n");
3209 					free(m_pFilteringTable);
3210 					return IPACM_FAILURE;
3211 				}
3212 				else
3213 				{
3214 					IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
3215 					IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
3216 				}
3217 				/* copy filter hdls */
3218 				dft_wan_fl_hdl[2] = m_pFilteringTable->rules[0].flt_rule_hdl;
3219 				/* End of construct ICMP rule */
3220 			}
3221 			else
3222 			{
3223 				IPACMDBG_H("in Q6_MHI_WAN mode, skip ICMPv6 flt rule \n");
3224 			}
3225 			/* v6 default route */
3226 			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
3227 			if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v6)) //rt_tbl_wan_v6 rt_tbl_v6
3228 			{
3229 				IPACMERR("m_routing.GetRoutingTable(rt_tbl_wan_v6) Failed.\n");
3230 				free(m_pFilteringTable);
3231 				return IPACM_FAILURE;
3232 			}
3233 
3234 			flt_rule_entry.flt_rule_hdl = -1;
3235 			flt_rule_entry.status = -1;
3236 			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl;
3237 
3238 			/* firewall disable, all traffic are allowed */
3239 			if(firewall_config.firewall_enable == true)
3240 			{
3241 				flt_rule_entry.at_rear = true;
3242 				/* default action for v6 is PASS_TO_ROUTE unless user set to exception*/
3243 				if(firewall_config.rule_action_accept == true)
3244 				{
3245 					flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
3246 				}
3247 				else
3248 				{
3249 			       flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
3250 				}
3251 			}
3252 			else
3253 			{
3254 			  flt_rule_entry.at_rear = true;
3255 			  flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
3256 			}
3257 			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
3258 				flt_rule_entry.rule.hashable = true;
3259 			memcpy(&flt_rule_entry.rule.attrib,
3260 						 &rx_prop->rx[0].attrib,
3261 						 sizeof(struct ipa_rule_attrib));
3262 			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
3263 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;
3264 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
3265 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
3266 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
3267 			flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000;
3268 			flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
3269 			flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
3270 			flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
3271 			/* disble meta-data filtering */
3272 			if(m_is_sta_mode == Q6_MHI_WAN)
3273 			{
3274 				flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA);
3275 				IPACMDBG_H("disable meta-data filtering 0x%x\n", flt_rule_entry.rule.attrib.attrib_mask);
3276 			}
3277 
3278 			memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3279 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
3280 			/* use index hw-counter */
3281 			if(IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
3282 			{
3283 				IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
3284 				result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL);
3285 			} else {
3286 				result = m_filtering.AddFilteringRule(m_pFilteringTable);
3287 			}
3288 #else
3289 			result = m_filtering.AddFilteringRule(m_pFilteringTable);
3290 #endif
3291 
3292 			if (false == result)
3293 			{
3294 				IPACMERR("Error Adding Filtering rules, aborting...\n");
3295 				free(m_pFilteringTable);
3296 				return IPACM_FAILURE;
3297 			}
3298 			else
3299 			{
3300 				IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
3301 				IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
3302 			}
3303 
3304 			/* copy filter hdls */
3305 			dft_wan_fl_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl;
3306 		}
3307 		else
3308 		{
3309 			memset(m_pFilteringTable, 0, len);
3310 
3311 			m_pFilteringTable->commit = 1;
3312 			m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
3313 			m_pFilteringTable->global = false;
3314 			m_pFilteringTable->ip = IPA_IP_v6;
3315 			m_pFilteringTable->num_rules = (uint8_t)1;
3316 
3317 			if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v6))
3318 			{
3319 				IPACMERR("m_routing.GetRoutingTable(rt_tbl_wan_v6) Failed.\n");
3320 				free(m_pFilteringTable);
3321 				return IPACM_FAILURE;
3322 			}
3323 
3324             if(firewall_config.firewall_enable == true)
3325             {
3326 			rule_v6 = 0;
3327 			for (i = 0; i < firewall_config.num_extd_firewall_entries; i++)
3328 			{
3329 				if (firewall_config.extd_firewall_entries[i].ip_vsn == 6)
3330 				{
3331 					memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
3332 
3333 		    			flt_rule_entry.at_rear = true;
3334 					flt_rule_entry.flt_rule_hdl = -1;
3335 					flt_rule_entry.status = -1;
3336 
3337 				    /* matched rules for v6 go PASS_TO_ROUTE */
3338                                     if(firewall_config.rule_action_accept == true)
3339 			            {
3340 			                flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
3341 			            }
3342 			            else
3343 			            {
3344 					flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
3345                                     }
3346 					if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
3347 						flt_rule_entry.rule.hashable = true;
3348 		    		flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl;
3349 					memcpy(&flt_rule_entry.rule.attrib,
3350 								 &firewall_config.extd_firewall_entries[i].attrib,
3351 								 sizeof(struct ipa_rule_attrib));
3352 					flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask;
3353 					flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask;
3354 					flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data;
3355 
3356 					/* check if the rule is define as TCP/UDP */
3357 					if (firewall_config.extd_firewall_entries[i].attrib.u.v6.next_hdr == IPACM_FIREWALL_IPPROTO_TCP_UDP)
3358 					{
3359 						/* insert TCP rule*/
3360 						flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP;
3361 						memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3362 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
3363 						/* use index hw-counter */
3364 						if(IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
3365 						{
3366 							IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
3367 							result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL);
3368 						} else {
3369 							result = m_filtering.AddFilteringRule(m_pFilteringTable);
3370 						}
3371 #else
3372 						result = m_filtering.AddFilteringRule(m_pFilteringTable);
3373 #endif
3374 
3375 						if (false == result)
3376 						{
3377 							IPACMERR("Error Adding Filtering rules, aborting...\n");
3378 							free(m_pFilteringTable);
3379 							return IPACM_FAILURE;
3380 						}
3381 						else
3382 						{
3383 							IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
3384 							/* save v4 firewall filter rule handler */
3385 							IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
3386 							firewall_hdl_v6[rule_v6] = m_pFilteringTable->rules[0].flt_rule_hdl;
3387 							num_firewall_v6++;
3388 							rule_v6++;
3389 						}
3390 
3391 						/* insert UDP rule*/
3392 						flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_UDP;
3393 						memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3394 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
3395 						/* use index hw-counter */
3396 						if(IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
3397 						{
3398 							IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
3399 							result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL);
3400 						} else {
3401 							result = m_filtering.AddFilteringRule(m_pFilteringTable);
3402 						}
3403 #else
3404 						result = m_filtering.AddFilteringRule(m_pFilteringTable);
3405 #endif
3406 						if (false == result)
3407 						{
3408 							IPACMERR("Error Adding Filtering rules, aborting...\n");
3409 							free(m_pFilteringTable);
3410 							return IPACM_FAILURE;
3411 						}
3412 						else
3413 						{
3414 							IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
3415 							/* save v6 firewall filter rule handler */
3416 							IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
3417 							firewall_hdl_v6[rule_v6] = m_pFilteringTable->rules[0].flt_rule_hdl;
3418 							num_firewall_v6++;
3419 							rule_v6++;
3420 						}
3421 					}
3422 					else
3423 					{
3424 						memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3425 
3426 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
3427 						/* use index hw-counter */
3428 						if(IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
3429 						{
3430 							IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
3431 							result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL);
3432 						} else {
3433 							result = m_filtering.AddFilteringRule(m_pFilteringTable);
3434 						}
3435 #else
3436 						result = m_filtering.AddFilteringRule(m_pFilteringTable);
3437 #endif
3438 						if (false == result)
3439 						{
3440 							IPACMERR("Error Adding Filtering rules, aborting...\n");
3441 							free(m_pFilteringTable);
3442 							return IPACM_FAILURE;
3443 						}
3444 						else
3445 						{
3446 							IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
3447 							/* save v6 firewall filter rule handler */
3448 							IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
3449 							firewall_hdl_v6[rule_v6] = m_pFilteringTable->rules[0].flt_rule_hdl;
3450 							num_firewall_v6++;
3451 							rule_v6++;
3452 						}
3453 					}
3454 				}
3455 			} /* end of firewall ipv6 filter rule add for loop*/
3456             }
3457 
3458 			/* Construct ICMP rule */
3459 			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
3460 			flt_rule_entry.at_rear = true;
3461 			flt_rule_entry.flt_rule_hdl = -1;
3462 			flt_rule_entry.status = -1;
3463 			flt_rule_entry.rule.retain_hdr = 1;
3464 			flt_rule_entry.rule.eq_attrib_type = 0;
3465 			flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
3466 			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
3467 				flt_rule_entry.rule.hashable = true;
3468 			memcpy(&flt_rule_entry.rule.attrib,
3469 					 &rx_prop->rx[0].attrib,
3470 					 sizeof(struct ipa_rule_attrib));
3471 			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
3472 			flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6;
3473 			memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3474 
3475 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
3476 			/* use index hw-counter */
3477 			if(IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
3478 			{
3479 				IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
3480 				result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL);
3481 			} else {
3482 				result = m_filtering.AddFilteringRule(m_pFilteringTable);
3483 			}
3484 #else
3485 			result = m_filtering.AddFilteringRule(m_pFilteringTable);
3486 #endif
3487 			if (result == false)
3488 			{
3489 				IPACMERR("Error Adding Filtering rules, aborting...\n");
3490 				free(m_pFilteringTable);
3491 				return IPACM_FAILURE;
3492 			}
3493 			else
3494 			{
3495 				IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
3496 				IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
3497 			}
3498 			/* copy filter hdls */
3499 			dft_wan_fl_hdl[2] = m_pFilteringTable->rules[0].flt_rule_hdl;
3500 			/* End of construct ICMP rule */
3501 
3502 			/* setup default wan filter rule */
3503 			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
3504 
3505 			flt_rule_entry.flt_rule_hdl = -1;
3506 			flt_rule_entry.status = -1;
3507 			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl;
3508 
3509 			/* firewall disable, all traffic are allowed */
3510                         if(firewall_config.firewall_enable == true)
3511 			{
3512 			   flt_rule_entry.at_rear = true;
3513 
3514 			   /* default action for v6 is PASS_TO_ROUTE unless user set to exception*/
3515                if(firewall_config.rule_action_accept == true)
3516 			   {
3517 			        flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
3518 			   }
3519 			   else
3520 			   {
3521 			flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
3522                            }
3523 		        }
3524 			else
3525 			{
3526 			  flt_rule_entry.at_rear = true;
3527 			  flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
3528                         }
3529 			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
3530 				flt_rule_entry.rule.hashable = true;
3531 			memcpy(&flt_rule_entry.rule.attrib,
3532 						 &rx_prop->rx[0].attrib,
3533 						 sizeof(struct ipa_rule_attrib));
3534 			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
3535 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;
3536 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
3537 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
3538 			flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
3539 			flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000;
3540 			flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
3541 			flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
3542 			flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
3543 
3544 			memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3545 
3546 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
3547 			/* use index hw-counter */
3548 			if(IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
3549 			{
3550 				IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
3551 				result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL);
3552 			} else {
3553 				result = m_filtering.AddFilteringRule(m_pFilteringTable);
3554 			}
3555 #else
3556 			result = m_filtering.AddFilteringRule(m_pFilteringTable);
3557 #endif
3558 
3559 			if (result == false)
3560 			{
3561 				IPACMERR("Error Adding Filtering rules, aborting...\n");
3562 				free(m_pFilteringTable);
3563 				return IPACM_FAILURE;
3564 			}
3565 			else
3566 			{
3567 				IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
3568 				IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
3569 			}
3570 			/* copy filter hdls*/
3571 			dft_wan_fl_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl;
3572 		}
3573 	}
3574 
3575 	if(m_pFilteringTable != NULL)
3576 	{
3577 		free(m_pFilteringTable);
3578 	}
3579 	return IPACM_SUCCESS;
3580 }
3581 
3582 /* configure the initial firewall filter rules */
config_dft_firewall_rules_ex(struct ipa_flt_rule_add * rules,int rule_offset,ipa_ip_type iptype)3583 int IPACM_Wan::config_dft_firewall_rules_ex(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype)
3584 {
3585 	struct ipa_flt_rule_add flt_rule_entry;
3586 	int i;
3587 	int num_rules = 0, original_num_rules = 0;
3588 	ipa_ioc_get_rt_tbl_indx rt_tbl_idx;
3589 	ipa_ioc_generate_flt_eq flt_eq;
3590 	int pos = rule_offset;
3591 
3592 	IPACMDBG_H("ip-family: %d; \n", iptype);
3593 
3594 	if (rx_prop == NULL)
3595 	{
3596 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
3597 		return IPACM_SUCCESS;
3598 	}
3599 
3600 	if(rules == NULL || rule_offset < 0)
3601 	{
3602 		IPACMERR("No filtering table is available.\n");
3603 		return IPACM_FAILURE;
3604 	}
3605 
3606 	/* default firewall is disable and the rule action is drop */
3607 	memset(&firewall_config, 0, sizeof(firewall_config));
3608 	strlcpy(firewall_config.firewall_config_file, "/etc/mobileap_firewall.xml", sizeof(firewall_config.firewall_config_file));
3609 
3610 	IPACMDBG_H("Firewall XML file is %s \n", firewall_config.firewall_config_file);
3611 	if (IPACM_SUCCESS == IPACM_read_firewall_xml(firewall_config.firewall_config_file, &firewall_config))
3612 	{
3613 		IPACMDBG_H("QCMAP Firewall XML read OK \n");
3614 	}
3615 	else
3616 	{
3617 		IPACMERR("QCMAP Firewall XML read failed, no that file, use default configuration \n");
3618 	}
3619 
3620 	/* add IPv6 frag rule when firewall is enabled*/
3621 	if(iptype == IPA_IP_v6 &&
3622 			firewall_config.firewall_enable == true &&
3623 			check_dft_firewall_rules_attr_mask(&firewall_config))
3624 	{
3625 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
3626 		flt_rule_entry.at_rear = true;
3627 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
3628 			flt_rule_entry.at_rear = false;
3629 		flt_rule_entry.flt_rule_hdl = -1;
3630 		flt_rule_entry.status = -1;
3631 
3632 		flt_rule_entry.rule.retain_hdr = 1;
3633 		flt_rule_entry.rule.to_uc = 0;
3634 		flt_rule_entry.rule.eq_attrib_type = 1;
3635 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
3636 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
3637 		{
3638 			flt_rule_entry.at_rear = false;
3639 			flt_rule_entry.rule.hashable = false;
3640 		}
3641 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
3642 		rt_tbl_idx.ip = IPA_IP_v6;
3643 		strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
3644 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
3645 		if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
3646 		{
3647 			IPACMERR("Failed to get routing table index from name\n");
3648 			return IPACM_FAILURE;
3649 		}
3650 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
3651 		IPACMDBG_H("IPv6 frag flt rule uses routing table index %d\n", rt_tbl_idx.idx);
3652 
3653 		flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask;
3654 		flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask;
3655 		flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data;
3656 
3657 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
3658 
3659 		change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
3660 
3661 		memset(&flt_eq, 0, sizeof(flt_eq));
3662 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
3663 		flt_eq.ip = IPA_IP_v6;
3664 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
3665 		{
3666 			IPACMERR("Failed to get eq_attrib\n");
3667 			return IPACM_FAILURE;
3668 		}
3669 		memcpy(&flt_rule_entry.rule.eq_attrib,
3670 			&flt_eq.eq_attrib,
3671 			sizeof(flt_rule_entry.rule.eq_attrib));
3672 
3673 		memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3674 		pos++;
3675 		IPACM_Wan::num_v6_flt_rule++;
3676 	}
3677 
3678 	if (iptype == IPA_IP_v4)
3679 	{
3680 		original_num_rules = IPACM_Wan::num_v4_flt_rule;
3681 		if(firewall_config.firewall_enable == true)
3682 		{
3683 			for (i = 0; i < firewall_config.num_extd_firewall_entries; i++)
3684 			{
3685 				if (firewall_config.extd_firewall_entries[i].ip_vsn == 4)
3686 				{
3687 					memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
3688 
3689 					flt_rule_entry.at_rear = true;
3690 					flt_rule_entry.flt_rule_hdl = -1;
3691 					flt_rule_entry.status = -1;
3692 
3693 					flt_rule_entry.rule.retain_hdr = 1;
3694 					flt_rule_entry.rule.to_uc = 0;
3695 					flt_rule_entry.rule.eq_attrib_type = 1;
3696 
3697 					/* Accept v4 matched rules*/
3698 					if(firewall_config.rule_action_accept == true)
3699 					{
3700 						flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
3701 					}
3702 					else
3703 					{
3704 						flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
3705 					}
3706 					if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
3707 						flt_rule_entry.rule.hashable = true;
3708 					memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
3709 					rt_tbl_idx.ip = iptype;
3710 					if(flt_rule_entry.rule.action == IPA_PASS_TO_ROUTING)
3711 					{
3712 						strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
3713 					}
3714 					else /*pass to dst nat*/
3715 					{
3716 						strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, IPA_RESOURCE_NAME_MAX);
3717 					}
3718 					rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
3719 					if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
3720 					{
3721 						IPACMERR("Failed to get routing table index from name\n");
3722 						return IPACM_FAILURE;
3723 					}
3724 					flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
3725 
3726 					IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
3727 
3728 					memcpy(&flt_rule_entry.rule.attrib,
3729 						&firewall_config.extd_firewall_entries[i].attrib,
3730 						sizeof(struct ipa_rule_attrib));
3731 
3732 					flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask;
3733 					flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask;
3734 					flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data;
3735 
3736 					change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib);
3737 
3738 					/* check if the rule is define as TCP_UDP, split into 2 rules, 1 for TCP and 1 UDP */
3739 					if (firewall_config.extd_firewall_entries[i].attrib.u.v4.protocol == IPACM_FIREWALL_IPPROTO_TCP_UDP)
3740 					{
3741 						/* insert TCP rule*/
3742 						flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_TCP;
3743 
3744 						memset(&flt_eq, 0, sizeof(flt_eq));
3745 						memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
3746 						flt_eq.ip = iptype;
3747 						if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
3748 						{
3749 							IPACMERR("Failed to get eq_attrib\n");
3750 							return IPACM_FAILURE;
3751 						}
3752 						memcpy(&flt_rule_entry.rule.eq_attrib,
3753 							&flt_eq.eq_attrib,
3754 							sizeof(flt_rule_entry.rule.eq_attrib));
3755 
3756 						memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3757 						IPACMDBG_H("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask);
3758 						pos++;
3759 						num_firewall_v4++;
3760 						IPACM_Wan::num_v4_flt_rule++;
3761 
3762 						/* insert UDP rule*/
3763 						flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_UDP;
3764 
3765 						memset(&flt_eq, 0, sizeof(flt_eq));
3766 						memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
3767 						flt_eq.ip = iptype;
3768 						if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
3769 						{
3770 							IPACMERR("Failed to get eq_attrib\n");
3771 							return IPACM_FAILURE;
3772 						}
3773 						memcpy(&flt_rule_entry.rule.eq_attrib,
3774 							&flt_eq.eq_attrib,
3775 							sizeof(flt_rule_entry.rule.eq_attrib));
3776 
3777 						memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3778 						IPACMDBG_H("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask);
3779 						pos++;
3780 						num_firewall_v4++;
3781 						IPACM_Wan::num_v4_flt_rule++;
3782 					}
3783 					else
3784 					{
3785 						memset(&flt_eq, 0, sizeof(flt_eq));
3786 						memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
3787 						flt_eq.ip = iptype;
3788 						if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
3789 						{
3790 							IPACMERR("Failed to get eq_attrib\n");
3791 							return IPACM_FAILURE;
3792 						}
3793 						memcpy(&flt_rule_entry.rule.eq_attrib,
3794 							&flt_eq.eq_attrib,
3795 							sizeof(flt_rule_entry.rule.eq_attrib));
3796 
3797 						memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3798 						IPACMDBG_H("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask);
3799 						pos++;
3800 						num_firewall_v4++;
3801 						IPACM_Wan::num_v4_flt_rule++;
3802 					}
3803 				}
3804 			} /* end of firewall ipv4 filter rule add for loop*/
3805 		}
3806 		/* configure default filter rule */
3807 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
3808 
3809 		flt_rule_entry.at_rear = true;
3810 		flt_rule_entry.flt_rule_hdl = -1;
3811 		flt_rule_entry.status = -1;
3812 
3813 		flt_rule_entry.rule.retain_hdr = 1;
3814 		flt_rule_entry.rule.to_uc = 0;
3815 		flt_rule_entry.rule.eq_attrib_type = 1;
3816 
3817 		/* firewall disable, all traffic are allowed */
3818 		if(firewall_config.firewall_enable == true)
3819 		{
3820 			/* default action for v4 is go DST_NAT unless user set to exception*/
3821 			if(firewall_config.rule_action_accept == true)
3822 			{
3823 				flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
3824 			}
3825 			else
3826 			{
3827 				flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
3828 			}
3829 		}
3830 		else
3831 		{
3832 			if(isWan_Bridge_Mode())
3833 			{
3834 				IPACMDBG_H("ODU is in bridge mode. \n");
3835 				flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
3836 			}
3837 			else
3838 			{
3839 				flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
3840 			}
3841 		}
3842 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
3843 			flt_rule_entry.rule.hashable = true;
3844 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
3845 		rt_tbl_idx.ip = iptype;
3846 
3847 		if(flt_rule_entry.rule.action == IPA_PASS_TO_ROUTING)
3848 		{
3849 			strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
3850 		}
3851 		else /*pass to dst nat*/
3852 		{
3853 			strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, IPA_RESOURCE_NAME_MAX);
3854 		}
3855 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
3856 
3857 		if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
3858 		{
3859 			IPACMERR("Failed to get routing table index from name\n");
3860 			return IPACM_FAILURE;
3861 		}
3862 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
3863 
3864 		IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
3865 
3866 		memcpy(&flt_rule_entry.rule.attrib,
3867 			&rx_prop->rx[0].attrib,
3868 			sizeof(struct ipa_rule_attrib));
3869 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
3870 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000;
3871 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000;
3872 
3873 		change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib);
3874 
3875 		memset(&flt_eq, 0, sizeof(flt_eq));
3876 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
3877 		flt_eq.ip = iptype;
3878 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
3879 		{
3880 			IPACMERR("Failed to get eq_attrib\n");
3881 			return IPACM_FAILURE;
3882 		}
3883 
3884 		memcpy(&flt_rule_entry.rule.eq_attrib,
3885 			&flt_eq.eq_attrib,
3886 			sizeof(flt_rule_entry.rule.eq_attrib));
3887 
3888 		memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3889 		IPACMDBG_H("Filter rule attrib mask: 0x%x\n",	rules[pos].rule.attrib.attrib_mask);
3890 		pos++;
3891 		num_firewall_v4++;
3892 		IPACM_Wan::num_v4_flt_rule++;
3893 
3894 		num_rules = IPACM_Wan::num_v4_flt_rule - original_num_rules - 1;
3895 	}
3896 	else
3897 	{
3898 		original_num_rules = IPACM_Wan::num_v6_flt_rule;
3899 
3900 		if(firewall_config.firewall_enable == true)
3901 		{
3902 			for (i = 0; i < firewall_config.num_extd_firewall_entries; i++)
3903 			{
3904 				if (firewall_config.extd_firewall_entries[i].ip_vsn == 6)
3905 				{
3906 					memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
3907 
3908 					flt_rule_entry.at_rear = true;
3909 					flt_rule_entry.flt_rule_hdl = -1;
3910 					flt_rule_entry.status = -1;
3911 
3912 					flt_rule_entry.rule.retain_hdr = 1;
3913 					flt_rule_entry.rule.to_uc = 0;
3914 					flt_rule_entry.rule.eq_attrib_type = 1;
3915 					flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
3916 					if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
3917 						flt_rule_entry.rule.hashable = true;
3918 					memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
3919 					rt_tbl_idx.ip = iptype;
3920 
3921 					/* matched rules for v6 go PASS_TO_ROUTE */
3922 					if(firewall_config.rule_action_accept == true)
3923 					{
3924 						strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX);
3925 					}
3926 					else
3927 					{
3928 						strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
3929 					}
3930 					rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
3931 
3932 					if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
3933 					{
3934 						IPACMERR("Failed to get routing table index from name\n");
3935 						return IPACM_FAILURE;
3936 					}
3937 					flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
3938 
3939 					IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
3940 
3941 					memcpy(&flt_rule_entry.rule.attrib,
3942 						&firewall_config.extd_firewall_entries[i].attrib,
3943 						sizeof(struct ipa_rule_attrib));
3944 
3945 					flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask;
3946 					flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask;
3947 					flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data;
3948 
3949 					change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
3950 
3951 					/* check if the rule is define as TCP/UDP */
3952 					if (firewall_config.extd_firewall_entries[i].attrib.u.v6.next_hdr == IPACM_FIREWALL_IPPROTO_TCP_UDP)
3953 					{
3954 						/* insert TCP rule*/
3955 						flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP;
3956 
3957 						memset(&flt_eq, 0, sizeof(flt_eq));
3958 						memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
3959 						flt_eq.ip = iptype;
3960 						if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
3961 						{
3962 							IPACMERR("Failed to get eq_attrib\n");
3963 							return IPACM_FAILURE;
3964 						}
3965 
3966 						memcpy(&flt_rule_entry.rule.eq_attrib,
3967 							&flt_eq.eq_attrib,
3968 							sizeof(flt_rule_entry.rule.eq_attrib));
3969 						memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3970 						pos++;
3971 						num_firewall_v6++;
3972 						IPACM_Wan::num_v6_flt_rule++;
3973 
3974 						/* insert UDP rule*/
3975 						flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_UDP;
3976 
3977 						memset(&flt_eq, 0, sizeof(flt_eq));
3978 						memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
3979 						flt_eq.ip = iptype;
3980 						if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
3981 						{
3982 							IPACMERR("Failed to get eq_attrib\n");
3983 							return IPACM_FAILURE;
3984 						}
3985 
3986 						memcpy(&flt_rule_entry.rule.eq_attrib,
3987 							&flt_eq.eq_attrib,
3988 							sizeof(flt_rule_entry.rule.eq_attrib));
3989 						memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
3990 						pos++;
3991 						num_firewall_v6++;
3992 						IPACM_Wan::num_v6_flt_rule++;
3993 					}
3994 					else
3995 					{
3996 						memset(&flt_eq, 0, sizeof(flt_eq));
3997 						memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
3998 						flt_eq.ip = iptype;
3999 						if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
4000 						{
4001 							IPACMERR("Failed to get eq_attrib\n");
4002 							return IPACM_FAILURE;
4003 						}
4004 
4005 						memcpy(&flt_rule_entry.rule.eq_attrib,
4006 							&flt_eq.eq_attrib,
4007 							sizeof(flt_rule_entry.rule.eq_attrib));
4008 						memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
4009 						pos++;
4010 						num_firewall_v6++;
4011 						IPACM_Wan::num_v6_flt_rule++;
4012 					}
4013 				}
4014 			} /* end of firewall ipv6 filter rule add for loop*/
4015 		}
4016 
4017 		/* setup default wan filter rule */
4018 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
4019 
4020 		flt_rule_entry.at_rear = true;
4021 		flt_rule_entry.flt_rule_hdl = -1;
4022 		flt_rule_entry.status = -1;
4023 
4024 		flt_rule_entry.rule.retain_hdr = 1;
4025 		flt_rule_entry.rule.to_uc = 0;
4026 		flt_rule_entry.rule.eq_attrib_type = 1;
4027 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
4028 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
4029 			flt_rule_entry.rule.hashable = true;
4030 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
4031 		rt_tbl_idx.ip = iptype;
4032 		/* firewall disable, all traffic are allowed */
4033 		if(firewall_config.firewall_enable == true)
4034 		{
4035 			/* default action for v6 is PASS_TO_ROUTE unless user set to exception*/
4036 			if(firewall_config.rule_action_accept == true)
4037 			{
4038 				strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
4039 			}
4040 			else
4041 			{
4042 				strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX);
4043 			}
4044 		}
4045 		else
4046 		{
4047 			strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX);
4048 		}
4049 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
4050 		if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
4051 		{
4052 			IPACMERR("Failed to get routing table index from name\n");
4053 			return IPACM_FAILURE;
4054 		}
4055 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
4056 
4057 		IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
4058 
4059 		memcpy(&flt_rule_entry.rule.attrib,
4060 			&rx_prop->rx[1].attrib,
4061 			sizeof(struct ipa_rule_attrib));
4062 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
4063 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;
4064 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
4065 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
4066 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
4067 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000;
4068 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
4069 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
4070 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
4071 
4072 		change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
4073 
4074 		memset(&flt_eq, 0, sizeof(flt_eq));
4075 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
4076 		flt_eq.ip = iptype;
4077 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
4078 		{
4079 			IPACMERR("Failed to get eq_attrib\n");
4080 			return IPACM_FAILURE;
4081 		}
4082 		memcpy(&flt_rule_entry.rule.eq_attrib,
4083 			&flt_eq.eq_attrib,
4084 			sizeof(flt_rule_entry.rule.eq_attrib));
4085 		memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
4086 		pos++;
4087 		num_firewall_v6++;
4088 		IPACM_Wan::num_v6_flt_rule++;
4089 
4090 		num_rules = IPACM_Wan::num_v6_flt_rule - original_num_rules - 1;
4091 	}
4092 	IPACMDBG_H("Constructed %d firewall rules for ip type %d\n", num_rules, iptype);
4093 	return IPACM_SUCCESS;
4094 }
4095 
init_fl_rule_ex(ipa_ip_type iptype)4096 int IPACM_Wan::init_fl_rule_ex(ipa_ip_type iptype)
4097 {
4098 	int res = IPACM_SUCCESS;
4099 
4100 	/* ADD corresponding ipa_rm_resource_name of RX-endpoint before adding all IPV4V6 FT-rules */
4101 	IPACMDBG_H(" dun add producer dependency from %s with registered rx-prop\n", dev_name);
4102 
4103 	if(iptype == IPA_IP_v4)
4104 	{
4105 		if(modem_ipv4_pdn_index == 0)	/* install ipv4 default modem DL filtering rules only once */
4106 		{
4107 			/* reset the num_v4_flt_rule*/
4108 			IPACM_Wan::num_v4_flt_rule = 0;
4109 			add_dft_filtering_rule(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4);
4110 		}
4111 	}
4112 	else if(iptype == IPA_IP_v6)
4113 	{
4114 		if(modem_ipv6_pdn_index == 0)	/* install ipv6 default modem DL filtering rules only once */
4115 		{
4116 			/* reset the num_v6_flt_rule*/
4117 			IPACM_Wan::num_v6_flt_rule = 0;
4118 			add_dft_filtering_rule(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6);
4119 		}
4120 	}
4121 	else
4122 	{
4123 		IPACMERR("IP type is not expected.\n");
4124 		res = IPACM_FAILURE;
4125 		goto fail;
4126 	}
4127 	install_wan_filtering_rule(false);
4128 
4129 	/* Add Natting iface to IPACM_Config if there is  Rx/Tx property */
4130 	if (rx_prop != NULL || tx_prop != NULL)
4131 	{
4132 		IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING \n", dev_name);
4133 		IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name, iptype);
4134 	}
4135 
4136 fail:
4137 	return res;
4138 }
4139 
add_icmp_alg_rules(struct ipa_flt_rule_add * rules,int rule_offset,ipa_ip_type iptype)4140 int IPACM_Wan::add_icmp_alg_rules(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype)
4141 {
4142 	int res = IPACM_SUCCESS, i, original_num_rules = 0, num_rules = 0;
4143 	struct ipa_flt_rule_add flt_rule_entry;
4144 	IPACM_Config* ipacm_config = IPACM_Iface::ipacmcfg;
4145 	ipa_ioc_generate_flt_eq flt_eq;
4146 	ipa_ioc_get_rt_tbl_indx rt_tbl_idx;
4147 
4148 	if(rules == NULL || rule_offset < 0)
4149 	{
4150 		IPACMERR("No filtering table is available.\n");
4151 		return IPACM_FAILURE;
4152 	}
4153 
4154 	if(iptype == IPA_IP_v4)
4155 	{
4156 		original_num_rules = IPACM_Wan::num_v4_flt_rule;
4157 
4158 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
4159 		strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
4160 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
4161 		rt_tbl_idx.ip = iptype;
4162 		if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
4163 		{
4164 			IPACMERR("Failed to get routing table index from name\n");
4165 			res = IPACM_FAILURE;
4166 			goto fail;
4167 		}
4168 
4169 		IPACMDBG_H("WAN DL routing table %s has index %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, rt_tbl_idx.idx);
4170 
4171 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
4172 
4173 		flt_rule_entry.at_rear = true;
4174 		flt_rule_entry.flt_rule_hdl = -1;
4175 		flt_rule_entry.status = -1;
4176 
4177 		flt_rule_entry.rule.retain_hdr = 1;
4178 		flt_rule_entry.rule.to_uc = 0;
4179 		flt_rule_entry.rule.eq_attrib_type = 1;
4180 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
4181 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
4182 			flt_rule_entry.rule.hashable = true;
4183 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
4184 
4185 		/* Configuring ICMP filtering rule */
4186 		memcpy(&flt_rule_entry.rule.attrib,
4187 					 &rx_prop->rx[0].attrib,
4188 					 sizeof(flt_rule_entry.rule.attrib));
4189 		/* Multiple PDNs may exist so keep meta-data */
4190 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
4191 		flt_rule_entry.rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP;
4192 
4193 		memset(&flt_eq, 0, sizeof(flt_eq));
4194 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
4195 		flt_eq.ip = iptype;
4196 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
4197 		{
4198 			IPACMERR("Failed to get eq_attrib\n");
4199 			res = IPACM_FAILURE;
4200 			goto fail;
4201 		}
4202 
4203 		memcpy(&flt_rule_entry.rule.eq_attrib,
4204 					 &flt_eq.eq_attrib,
4205 					 sizeof(flt_rule_entry.rule.eq_attrib));
4206 
4207 		memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
4208 
4209 		IPACM_Wan::num_v4_flt_rule++;
4210 
4211 		/* Configure ALG filtering rules */
4212 		/* maintain meta data mask */
4213 		memcpy(&flt_rule_entry.rule.attrib,
4214 					 &rx_prop->rx[0].attrib,
4215 					 sizeof(flt_rule_entry.rule.attrib));
4216 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_PORT;
4217 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
4218 		for(i = 0; i < ipacm_config->ipa_num_alg_ports; i++)
4219 		{
4220 			flt_rule_entry.rule.attrib.src_port = ipacm_config->alg_table[i].port;
4221 			flt_rule_entry.rule.attrib.u.v4.protocol = ipacm_config->alg_table[i].protocol;
4222 
4223 			memset(&flt_eq, 0, sizeof(flt_eq));
4224 			memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
4225 			flt_eq.ip = iptype;
4226 			if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
4227 			{
4228 				IPACMERR("Failed to get eq_attrib\n");
4229 				res = IPACM_FAILURE;
4230 				goto fail;
4231 			}
4232 			memcpy(&flt_rule_entry.rule.eq_attrib,
4233 						 &flt_eq.eq_attrib,
4234 						 sizeof(flt_rule_entry.rule.eq_attrib));
4235 			memcpy(&(rules[rule_offset + 1 + i]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
4236 			IPACM_Wan::num_v4_flt_rule++;
4237 		}
4238 
4239 		/* maintain meta data mask */
4240 		memcpy(&flt_rule_entry.rule.attrib,
4241 					 &rx_prop->rx[0].attrib,
4242 					 sizeof(flt_rule_entry.rule.attrib));
4243 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_PORT;
4244 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
4245 		for(i = 0; i < ipacm_config->ipa_num_alg_ports; i++)
4246 		{
4247 			flt_rule_entry.rule.attrib.dst_port = ipacm_config->alg_table[i].port;
4248 			flt_rule_entry.rule.attrib.u.v4.protocol = ipacm_config->alg_table[i].protocol;
4249 
4250 			memset(&flt_eq, 0, sizeof(flt_eq));
4251 			memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
4252 			flt_eq.ip = iptype;
4253 			if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
4254 			{
4255 				IPACMERR("Failed to get eq_attrib\n");
4256 				res = IPACM_FAILURE;
4257 				goto fail;
4258 			}
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(&(rules[rule_offset + ipacm_config->ipa_num_alg_ports + 1 + i]),
4265 				&flt_rule_entry,
4266 				sizeof(struct ipa_flt_rule_add));
4267 			IPACM_Wan::num_v4_flt_rule++;
4268 		}
4269 		num_rules = IPACM_Wan::num_v4_flt_rule - original_num_rules;
4270 	}
4271 	else /* IPv6 case */
4272 	{
4273 		original_num_rules = IPACM_Wan::num_v6_flt_rule;
4274 
4275 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
4276 		strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
4277 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
4278 		rt_tbl_idx.ip = iptype;
4279 		if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
4280 		{
4281 			IPACMERR("Failed to get routing table index from name\n");
4282 			res = IPACM_FAILURE;
4283 			goto fail;
4284 		}
4285 
4286 		IPACMDBG_H("WAN DL routing table %s has index %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, rt_tbl_idx.idx);
4287 
4288 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
4289 
4290 		flt_rule_entry.at_rear = true;
4291 		flt_rule_entry.flt_rule_hdl = -1;
4292 		flt_rule_entry.status = -1;
4293 
4294 		flt_rule_entry.rule.retain_hdr = 1;
4295 		flt_rule_entry.rule.to_uc = 0;
4296 		flt_rule_entry.rule.eq_attrib_type = 1;
4297 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
4298 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
4299 			flt_rule_entry.rule.hashable = true;
4300 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
4301 
4302 		/* Configuring ICMP filtering rule */
4303 		memcpy(&flt_rule_entry.rule.attrib,
4304 					 &rx_prop->rx[1].attrib,
4305 					 sizeof(flt_rule_entry.rule.attrib));
4306 		/* Multiple PDNs may exist so keep meta-data */
4307 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
4308 		flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6;
4309 
4310 		memset(&flt_eq, 0, sizeof(flt_eq));
4311 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
4312 		flt_eq.ip = iptype;
4313 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
4314 		{
4315 			IPACMERR("Failed to get eq_attrib\n");
4316 			res = IPACM_FAILURE;
4317 			goto fail;
4318 		}
4319 
4320 		memcpy(&flt_rule_entry.rule.eq_attrib,
4321 					 &flt_eq.eq_attrib,
4322 					 sizeof(flt_rule_entry.rule.eq_attrib));
4323 
4324 		memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
4325 		IPACM_Wan::num_v6_flt_rule++;
4326 
4327 		num_rules = IPACM_Wan::num_v6_flt_rule - original_num_rules;
4328 	}
4329 
4330 fail:
4331 	IPACMDBG_H("Constructed %d ICMP/ALG rules for ip type %d\n", num_rules, iptype);
4332 		return res;
4333 }
4334 
query_ext_prop()4335 int IPACM_Wan::query_ext_prop()
4336 {
4337 	int fd, ret = IPACM_SUCCESS;
4338 	uint32_t cnt;
4339 
4340 	if (iface_query->num_ext_props > 0)
4341 	{
4342 		fd = open(IPA_DEVICE_NAME, O_RDWR);
4343 		IPACMDBG_H("iface query-property \n");
4344 		if (0 == fd)
4345 		{
4346 			IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
4347 			return IPACM_FAILURE;
4348 		}
4349 
4350 		ext_prop = (struct ipa_ioc_query_intf_ext_props *)
4351 			 calloc(1, sizeof(struct ipa_ioc_query_intf_ext_props) +
4352 							iface_query->num_ext_props * sizeof(struct ipa_ioc_ext_intf_prop));
4353 		if(ext_prop == NULL)
4354 		{
4355 			IPACMERR("Unable to allocate memory.\n");
4356 			return IPACM_FAILURE;
4357 		}
4358 		memcpy(ext_prop->name, dev_name,
4359 					 sizeof(dev_name));
4360 		ext_prop->num_ext_props = iface_query->num_ext_props;
4361 
4362 		IPACMDBG_H("Query extended property for iface %s\n", ext_prop->name);
4363 
4364 		ret = ioctl(fd, IPA_IOC_QUERY_INTF_EXT_PROPS, ext_prop);
4365 		if (ret < 0)
4366 		{
4367 			IPACMERR("ioctl IPA_IOC_QUERY_INTF_EXT_PROPS failed\n");
4368 			/* ext_prop memory will free when iface-down*/
4369 			free(ext_prop);
4370 			close(fd);
4371 			return ret;
4372 		}
4373 
4374 		IPACMDBG_H("Wan interface has %d tx props, %d rx props and %d ext props\n",
4375 				iface_query->num_tx_props, iface_query->num_rx_props, iface_query->num_ext_props);
4376 
4377 		for (cnt = 0; cnt < ext_prop->num_ext_props; cnt++)
4378 		{
4379 			if (!IPACM_Iface::ipacmcfg->isIPAv3Supported())
4380 			{
4381 				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",
4382 					cnt, ext_prop->ext[cnt].ip, ext_prop->ext[cnt].mux_id, ext_prop->ext[cnt].action,
4383 					ext_prop->ext[cnt].rt_tbl_idx, ext_prop->ext[cnt].is_xlat_rule, ext_prop->ext[cnt].filter_hdl);
4384 			}
4385 			else /* IPA_V3 */
4386 			{
4387 				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",
4388 					cnt, ext_prop->ext[cnt].ip, ext_prop->ext[cnt].mux_id, ext_prop->ext[cnt].action,
4389 					ext_prop->ext[cnt].rt_tbl_idx, ext_prop->ext[cnt].is_xlat_rule, ext_prop->ext[cnt].rule_id);
4390 			}
4391 		}
4392 
4393 		if(IPACM_Wan::is_ext_prop_set == false)
4394 		{
4395 			IPACM_Iface::ipacmcfg->SetExtProp(ext_prop);
4396 			IPACM_Wan::is_ext_prop_set = true;
4397 		}
4398 		close(fd);
4399 	}
4400 	return IPACM_SUCCESS;
4401 }
4402 
config_wan_firewall_rule(ipa_ip_type iptype)4403 int IPACM_Wan::config_wan_firewall_rule(ipa_ip_type iptype)
4404 {
4405 	int res = IPACM_SUCCESS;
4406 
4407 	IPACMDBG_H("Configure WAN DL firewall rules.\n");
4408 
4409 	if(iptype == IPA_IP_v4)
4410 	{
4411 		IPACM_Wan::num_v4_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4;
4412 		if(IPACM_FAILURE == add_icmp_alg_rules(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4))
4413 		{
4414 			IPACMERR("Failed to add ICMP and ALG port filtering rules.\n");
4415 			res = IPACM_FAILURE;
4416 			goto fail;
4417 		}
4418 		IPACMDBG_H("Succeded in constructing ICMP/ALG rules for ip type %d\n", iptype);
4419 
4420 		if(IPACM_FAILURE == config_dft_firewall_rules_ex(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4))
4421 		{
4422 			IPACMERR("Failed to add firewall filtering rules.\n");
4423 			res = IPACM_FAILURE;
4424 			goto fail;
4425 		}
4426 		IPACMDBG_H("Succeded in constructing firewall rules for ip type %d\n", iptype);
4427 	}
4428 	else if(iptype == IPA_IP_v6)
4429 	{
4430 		IPACM_Wan::num_v6_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6;
4431 		if(IPACM_FAILURE == add_icmp_alg_rules(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6))
4432 		{
4433 			IPACMERR("Failed to add ICMP and ALG port filtering rules.\n");
4434 			res = IPACM_FAILURE;
4435 			goto fail;
4436 		}
4437 		IPACMDBG_H("Succeded in constructing ICMP/ALG rules for ip type %d\n", iptype);
4438 
4439 		if(IPACM_FAILURE == config_dft_firewall_rules_ex(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6))
4440 		{
4441 			IPACMERR("Failed to add firewall filtering rules.\n");
4442 			res = IPACM_FAILURE;
4443 			goto fail;
4444 		}
4445 		IPACMDBG_H("Succeded in constructing firewall rules for ip type %d\n", iptype);
4446 	}
4447 	else
4448 	{
4449 		IPACMERR("IP type is not expected.\n");
4450 		return IPACM_FAILURE;
4451 	}
4452 
4453 fail:
4454 	return res;
4455 }
4456 
add_dft_filtering_rule(struct ipa_flt_rule_add * rules,int rule_offset,ipa_ip_type iptype)4457 int IPACM_Wan::add_dft_filtering_rule(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype)
4458 {
4459 	struct ipa_ioc_get_rt_tbl_indx rt_tbl_idx;
4460 	struct ipa_flt_rule_add flt_rule_entry;
4461 	struct ipa_ioc_generate_flt_eq flt_eq;
4462 	int res = IPACM_SUCCESS;
4463 
4464 	if(rules == NULL)
4465 	{
4466 		IPACMERR("No filtering table available.\n");
4467 		return IPACM_FAILURE;
4468 	}
4469 	if(rx_prop == NULL)
4470 	{
4471 		IPACMERR("No tx property.\n");
4472 		return IPACM_FAILURE;
4473 	}
4474 
4475 	if (iptype == IPA_IP_v4)
4476 	{
4477 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
4478 		strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
4479 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
4480 		rt_tbl_idx.ip = iptype;
4481 		if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
4482 		{
4483 			IPACMERR("Failed to get routing table index from name\n");
4484 			res = IPACM_FAILURE;
4485 			goto fail;
4486 		}
4487 
4488 		IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
4489 
4490 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
4491 
4492 		flt_rule_entry.at_rear = true;
4493 		flt_rule_entry.flt_rule_hdl = -1;
4494 		flt_rule_entry.status = -1;
4495 
4496 		flt_rule_entry.rule.retain_hdr = 1;
4497 		flt_rule_entry.rule.to_uc = 0;
4498 		flt_rule_entry.rule.eq_attrib_type = 1;
4499 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
4500 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
4501 			flt_rule_entry.rule.hashable = true;
4502 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
4503 
4504 		IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
4505 
4506 		/* Configuring Multicast Filtering Rule */
4507 		memcpy(&flt_rule_entry.rule.attrib,
4508 					 &rx_prop->rx[0].attrib,
4509 					 sizeof(flt_rule_entry.rule.attrib));
4510 		/* remove meta data mask since we only install default flt rules once for all modem PDN*/
4511 		flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA);
4512 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
4513 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xF0000000;
4514 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000;
4515 
4516 		change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib);
4517 
4518 		memset(&flt_eq, 0, sizeof(flt_eq));
4519 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
4520 		flt_eq.ip = iptype;
4521 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
4522 		{
4523 			IPACMERR("Failed to get eq_attrib\n");
4524 			res = IPACM_FAILURE;
4525 			goto fail;
4526 		}
4527 
4528 		memcpy(&flt_rule_entry.rule.eq_attrib,
4529 					 &flt_eq.eq_attrib,
4530 					 sizeof(flt_rule_entry.rule.eq_attrib));
4531 		memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
4532 
4533 		/* Configuring Broadcast Filtering Rule */
4534 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
4535 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF;
4536 
4537 		change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib);
4538 
4539 		memset(&flt_eq, 0, sizeof(flt_eq));
4540 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
4541 		flt_eq.ip = iptype;
4542 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
4543 		{
4544 			IPACMERR("Failed to get eq_attrib\n");
4545 			res = IPACM_FAILURE;
4546 			goto fail;
4547 		}
4548 
4549 		memcpy(&flt_rule_entry.rule.eq_attrib,
4550 					 &flt_eq.eq_attrib,
4551 					 sizeof(flt_rule_entry.rule.eq_attrib));
4552 		memcpy(&(rules[rule_offset + 1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
4553 
4554 		IPACM_Wan::num_v4_flt_rule += IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4;
4555 		IPACMDBG_H("Constructed %d default filtering rules for ip type %d\n", IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4, iptype);
4556 	}
4557 	else	/*insert rules for ipv6*/
4558 	{
4559 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
4560 		strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
4561 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
4562 		rt_tbl_idx.ip = iptype;
4563 		if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
4564 		{
4565 			IPACMERR("Failed to get routing table index from name\n");
4566 			res = IPACM_FAILURE;
4567 			goto fail;
4568 		}
4569 
4570 		IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
4571 
4572 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
4573 
4574 		flt_rule_entry.at_rear = true;
4575 		flt_rule_entry.flt_rule_hdl = -1;
4576 		flt_rule_entry.status = -1;
4577 
4578 		flt_rule_entry.rule.retain_hdr = 1;
4579 		flt_rule_entry.rule.to_uc = 0;
4580 		flt_rule_entry.rule.eq_attrib_type = 1;
4581 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
4582 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
4583 			flt_rule_entry.rule.hashable = true;
4584 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
4585 
4586 		/* Configuring Multicast Filtering Rule */
4587 		memcpy(&flt_rule_entry.rule.attrib,
4588 					 &rx_prop->rx[0].attrib,
4589 					 sizeof(flt_rule_entry.rule.attrib));
4590 		/* remove meta data mask since we only install default flt rules once for all modem PDN*/
4591 		flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA);
4592 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
4593 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
4594 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
4595 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
4596 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
4597 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFF000000;
4598 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
4599 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
4600 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0x00000000;
4601 
4602 		change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
4603 
4604 		memset(&flt_eq, 0, sizeof(flt_eq));
4605 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
4606 		flt_eq.ip = iptype;
4607 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
4608 		{
4609 			IPACMERR("Failed to get eq_attrib\n");
4610 			res = IPACM_FAILURE;
4611 			goto fail;
4612 		}
4613 
4614 		memcpy(&flt_rule_entry.rule.eq_attrib,
4615 					 &flt_eq.eq_attrib,
4616 					 sizeof(flt_rule_entry.rule.eq_attrib));
4617 		memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
4618 
4619 		/* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */
4620 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFC00000;
4621 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
4622 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
4623 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
4624 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFE800000;
4625 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
4626 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
4627 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0x00000000;
4628 
4629 		change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
4630 
4631 		memset(&flt_eq, 0, sizeof(flt_eq));
4632 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
4633 		flt_eq.ip = iptype;
4634 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
4635 		{
4636 			IPACMERR("Failed to get eq_attrib\n");
4637 			res = IPACM_FAILURE;
4638 			goto fail;
4639 		}
4640 
4641 		memcpy(&flt_rule_entry.rule.eq_attrib,
4642 					 &flt_eq.eq_attrib,
4643 					 sizeof(flt_rule_entry.rule.eq_attrib));
4644 
4645 		memcpy(&(rules[rule_offset + 1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
4646 
4647 		/* Configuring fec0::/10 Reserved by IETF Filtering Rule */
4648 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFC00000;
4649 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
4650 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
4651 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
4652 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFEC00000;
4653 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
4654 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
4655 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0x00000000;
4656 
4657 		change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
4658 
4659 		memset(&flt_eq, 0, sizeof(flt_eq));
4660 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
4661 		flt_eq.ip = iptype;
4662 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
4663 		{
4664 			IPACMERR("Failed to get eq_attrib\n");
4665 			res = IPACM_FAILURE;
4666 			goto fail;
4667 		}
4668 
4669 		memcpy(&flt_rule_entry.rule.eq_attrib,
4670 					 &flt_eq.eq_attrib,
4671 					 sizeof(flt_rule_entry.rule.eq_attrib));
4672 
4673 		memcpy(&(rules[rule_offset + 2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
4674 
4675 		/* Configuring fragment Filtering Rule */
4676 		flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_DST_ADDR);
4677 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
4678 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
4679 		flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP;
4680 
4681 		memset(&flt_eq, 0, sizeof(flt_eq));
4682 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
4683 		flt_eq.ip = iptype;
4684 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
4685 		{
4686 			IPACMERR("Failed to get eq_attrib\n");
4687 			res = IPACM_FAILURE;
4688 			goto fail;
4689 		}
4690 
4691 		memcpy(&flt_rule_entry.rule.eq_attrib,
4692 					 &flt_eq.eq_attrib,
4693 					 sizeof(flt_rule_entry.rule.eq_attrib));
4694 
4695 		memcpy(&(rules[rule_offset + 3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
4696 
4697 #ifdef FEATURE_IPA_ANDROID
4698 		IPACM_Wan::num_v6_flt_rule += IPA_V2_NUM_MULTICAST_WAN_FILTER_RULE_IPV6;
4699 		IPACMDBG_H("Constructed %d default filtering rules for ip type %d\n", IPA_V2_NUM_MULTICAST_WAN_FILTER_RULE_IPV6, iptype);
4700 #else
4701 		IPACM_Wan::num_v6_flt_rule += IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6;
4702 		IPACMDBG_H("Constructed %d default filtering rules for ip type %d\n",
4703 				IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6, iptype);
4704 #endif
4705 		IPACM_Wan::num_v6_flt_rule += IPA_V2_NUM_FRAG_WAN_FILTER_RULE_IPV6;
4706 		IPACMDBG_H("Constructed %d default filtering rules for ip type %d\n",
4707 				IPA_V2_NUM_FRAG_WAN_FILTER_RULE_IPV6, iptype);
4708 	}
4709 
4710 fail:
4711 	return res;
4712 }
4713 
del_wan_firewall_rule(ipa_ip_type iptype)4714 int IPACM_Wan::del_wan_firewall_rule(ipa_ip_type iptype)
4715 {
4716 	if(iptype == IPA_IP_v4)
4717 	{
4718 		IPACM_Wan::num_v4_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4;
4719 		memset(&IPACM_Wan::flt_rule_v4[IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4], 0,
4720 			(IPA_MAX_FLT_RULE - IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4) * sizeof(struct ipa_flt_rule_add));
4721 	}
4722 	else if(iptype == IPA_IP_v6)
4723 	{
4724 		IPACM_Wan::num_v6_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6;
4725 		memset(&IPACM_Wan::flt_rule_v6[IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6], 0,
4726 			(IPA_MAX_FLT_RULE - IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6) * sizeof(struct ipa_flt_rule_add));
4727 	}
4728 	else
4729 	{
4730 		IPACMERR("IP type is not expected.\n");
4731 		return IPACM_FAILURE;
4732 	}
4733 
4734 	return IPACM_SUCCESS;
4735 }
4736 
4737 /*for STA mode: clean firewall filter rules */
del_dft_firewall_rules(ipa_ip_type iptype)4738 int IPACM_Wan::del_dft_firewall_rules(ipa_ip_type iptype)
4739 {
4740 	/* free v4 firewall filter rule */
4741 	if (rx_prop == NULL)
4742 	{
4743 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
4744 		return IPACM_SUCCESS;
4745 	}
4746 
4747 	if ((iptype == IPA_IP_v4) && (active_v4 == true))
4748 	{
4749 		if (num_firewall_v4 > IPACM_MAX_FIREWALL_ENTRIES)
4750 		{
4751 			IPACMERR("the number of v4 firewall entries overflow, aborting...\n");
4752 			return IPACM_FAILURE;
4753 		}
4754 		if (num_firewall_v4 != 0)
4755 		{
4756 			if (m_filtering.DeleteFilteringHdls(firewall_hdl_v4,
4757 				IPA_IP_v4, num_firewall_v4) == false)
4758 			{
4759 				IPACMERR("Error Deleting Filtering rules, aborting...\n");
4760 				return IPACM_FAILURE;
4761 			}
4762 			IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, num_firewall_v4);
4763 		}
4764 		else
4765 		{
4766 			IPACMDBG_H("No ipv4 firewall rules, no need deleted\n");
4767 		}
4768 
4769 		if (m_filtering.DeleteFilteringHdls(dft_wan_fl_hdl,
4770 				IPA_IP_v4, 1) == false)
4771 		{
4772 			IPACMERR("Error Deleting Filtering rules, aborting...\n");
4773 			return IPACM_FAILURE;
4774 		}
4775 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
4776 
4777 		num_firewall_v4 = 0;
4778 	}
4779 
4780 	/* free v6 firewall filter rule */
4781 	if ((iptype == IPA_IP_v6) && (active_v6 == true))
4782 	{
4783 		if (num_firewall_v6 > IPACM_MAX_FIREWALL_ENTRIES)
4784 		{
4785 			IPACMERR("the number of v6 firewall entries overflow, aborting...\n");
4786 			return IPACM_FAILURE;
4787 		}
4788 		if (num_firewall_v6 != 0)
4789 		{
4790 			if (m_filtering.DeleteFilteringHdls(firewall_hdl_v6,
4791 				IPA_IP_v6, num_firewall_v6) == false)
4792 			{
4793 				IPACMERR("Error Deleting Filtering rules, aborting...\n");
4794 				return IPACM_FAILURE;
4795 			}
4796 			IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, num_firewall_v6);
4797 		}
4798 		else
4799 		{
4800 			IPACMDBG_H("No ipv6 firewall rules, no need deleted\n");
4801 		}
4802 
4803 		if (m_filtering.DeleteFilteringHdls(&dft_wan_fl_hdl[1],
4804 			IPA_IP_v6, 1) == false)
4805 		{
4806 			IPACMERR("Error Deleting Filtering rules, aborting...\n");
4807 			return IPACM_FAILURE;
4808 		}
4809 
4810 		if(m_is_sta_mode != Q6_MHI_WAN)
4811 		{
4812 			IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
4813 			if (m_filtering.DeleteFilteringHdls(&dft_wan_fl_hdl[2],
4814 				IPA_IP_v6, 1) == false)
4815 			{
4816 				IPACMERR("Error Deleting Filtering rules, aborting...\n");
4817 				return IPACM_FAILURE;
4818 			}
4819 			IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
4820 		}
4821 		else
4822 		{
4823 			IPACMDBG_H("in Q6_MHI_WAN mode, skip ICMPv6 flt rule deletion\n");
4824 		}
4825 		if (is_ipv6_frag_firewall_flt_rule_installed &&
4826 			check_dft_firewall_rules_attr_mask(&firewall_config))
4827 		{
4828 			if (m_filtering.DeleteFilteringHdls(&ipv6_frag_firewall_flt_rule_hdl, IPA_IP_v6, 1) == false)
4829 			{
4830 				IPACMERR("Error deleting IPv6 frag filtering rules.\n");
4831 				return IPACM_FAILURE;
4832 			}
4833 			is_ipv6_frag_firewall_flt_rule_installed = false;
4834 			IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
4835 		}
4836 		num_firewall_v6 = 0;
4837 	}
4838 	return IPACM_SUCCESS;
4839 }
4840 
4841 /* for STA mode: wan default route/filter rule delete */
handle_route_del_evt(ipa_ip_type iptype,bool delete_only)4842 int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype, bool delete_only)
4843 {
4844 	uint32_t tx_index;
4845 	ipacm_cmd_q_data evt_data;
4846 #ifdef WAN_IOC_NOTIFY_WAN_STATE
4847 	struct wan_ioctl_notify_wan_state wan_state;
4848 	int fd_wwan_ioctl;
4849 	memset(&wan_state, 0, sizeof(wan_state));
4850 #endif
4851 	int ret = IPACM_SUCCESS;
4852 
4853 	IPACMDBG_H("got handle_route_del_evt for STA-mode with ip-family:%d \n", iptype);
4854 
4855 	if(tx_prop == NULL)
4856 	{
4857 		IPACMDBG_H("No tx properties, ignore delete default route setting\n");
4858 		return IPACM_SUCCESS;
4859 	}
4860 
4861 	is_default_gateway = false;
4862 	IPACMDBG_H("Default route is deleted to iface %s.\n", dev_name);
4863 
4864 	if (((iptype == IPA_IP_v4) && (active_v4 == true)) ||
4865 			((iptype == IPA_IP_v6) && (active_v6 == true)))
4866 	{
4867 		if (!delete_only)
4868 		{
4869 			if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_None && IPACM_Iface::ipacmcfg->GetIPAVer() < IPA_HW_v4_0)
4870 			{
4871 				/* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */
4872 				IPACMDBG_H("dev %s delete producer dependency\n", dev_name);
4873 				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]);
4874 				IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
4875 			}
4876 			else
4877 			{
4878 				/* change wan_state for Q6_MHI */
4879 #ifdef WAN_IOC_NOTIFY_WAN_STATE
4880 				IPACMDBG_H("ipa_pm_q6_check to %d\n", ipa_pm_q6_check);
4881 				if(ipa_pm_q6_check == 1 && m_is_sta_mode == Q6_MHI_WAN)
4882 				{
4883 					fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
4884 					if(fd_wwan_ioctl < 0)
4885 					{
4886 						IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME);
4887 						return false;
4888 					}
4889 					IPACMDBG_H("send WAN_IOC_NOTIFY_WAN_STATE down to IPA_PM\n");
4890 					if(ioctl(fd_wwan_ioctl, WAN_IOC_NOTIFY_WAN_STATE, &wan_state))
4891 					{
4892 						IPACMERR("Failed to send WAN_IOC_NOTIFY_WAN_STATE as up %d\n ", wan_state.up);
4893 					}
4894 					close(fd_wwan_ioctl);
4895 				}
4896 				if (ipa_pm_q6_check > 0)
4897 					ipa_pm_q6_check--;
4898 				else
4899 					IPACMERR(" ipa_pm_q6_check becomes negative !!!\n");
4900 #endif
4901 			}
4902 		} // end of delete_only
4903 
4904 		for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
4905 		{
4906 		    if(iptype != tx_prop->tx[tx_index].ip)
4907 		    {
4908 		    	IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d, no RT-rule deleted\n",
4909 		    					    tx_index, tx_prop->tx[tx_index].ip,iptype);
4910 		    	continue;
4911 		    }
4912 
4913 			if (iptype == IPA_IP_v4)
4914 			{
4915 		    	IPACMDBG_H("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n", tx_index, tx_prop->tx[tx_index].ip,iptype);
4916 
4917 				if (m_routing.DeleteRoutingHdl(wan_route_rule_v4_hdl[tx_index], IPA_IP_v4) == false)
4918 				{
4919 					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);
4920 					return IPACM_FAILURE;
4921 				}
4922 			}
4923 			else
4924 			{
4925 		    	IPACMDBG_H("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n", tx_index, tx_prop->tx[tx_index].ip,iptype);
4926 
4927 				if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl[tx_index], IPA_IP_v6) == false)
4928 				{
4929 					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);
4930 					return IPACM_FAILURE;
4931 				}
4932 			}
4933 		}
4934 
4935 		/* Delete the default wan route*/
4936 		if (iptype == IPA_IP_v6 && m_is_sta_mode != Q6_MHI_WAN)
4937 		{
4938 		   	IPACMDBG_H("ip-type %d: default v6 wan RT-rule deleted\n",iptype);
4939 			if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl_a5[0], IPA_IP_v6) == false)
4940 			{
4941 			IPACMDBG_H("IP-family:%d, Routing rule(hdl:0x%x) deletion failed!\n",IPA_IP_v6,wan_route_rule_v6_hdl_a5[0]);
4942 				return IPACM_FAILURE;
4943 			}
4944 		}
4945 
4946 		/* support delete only, not post wan_down event */
4947 		if(delete_only)
4948 		{
4949 			IPACMDBG_H(" Only delete default WAN routing rules (%d)\n", delete_only);
4950 			return IPACM_SUCCESS;
4951 		}
4952 
4953 		ipacm_event_iface_up *wandown_data;
4954 		wandown_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up));
4955 		if (wandown_data == NULL)
4956 		{
4957 			IPACMERR("Unable to allocate memory\n");
4958 			return IPACM_FAILURE;
4959 		}
4960 		memset(wandown_data, 0, sizeof(ipacm_event_iface_up));
4961 
4962 		if (iptype == IPA_IP_v4)
4963 		{
4964 			wandown_data->ipv4_addr = wan_v4_addr;
4965 			wandown_data->backhaul_type = m_is_sta_mode;
4966 			evt_data.event = IPA_HANDLE_WAN_DOWN;
4967 			evt_data.evt_data = (void *)wandown_data;
4968 			/* Insert IPA_HANDLE_WAN_DOWN to command queue */
4969 			IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN for IPv4 (%d.%d.%d.%d) \n",
4970 					(unsigned char)(wandown_data->ipv4_addr),
4971 					(unsigned char)(wandown_data->ipv4_addr >> 8),
4972 					(unsigned char)(wandown_data->ipv4_addr >> 16),
4973 					(unsigned char)(wandown_data->ipv4_addr >> 24));
4974 
4975 			IPACM_EvtDispatcher::PostEvt(&evt_data);
4976 			IPACMDBG_H("setup wan_up/active_v4= false \n");
4977 			IPACM_Wan::wan_up = false;
4978 			active_v4 = false;
4979 			if(IPACM_Wan::wan_up_v6)
4980 			{
4981 				IPACMDBG_H("modem v6-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name);
4982 			}
4983 			else
4984 			{
4985 				memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name));
4986 			}
4987 
4988 			/* Delete MHI frag rule */
4989 			if(delete_offload_frag_rule())
4990 			{
4991 				IPACMERR("Failed to delete DL frag rule \n");
4992 				ret = IPACM_FAILURE;
4993 			}
4994 
4995 			/* Delete tcp_fin_rst rule */
4996 			if(delete_tcp_fin_rst_exception_rule())
4997 			{
4998 				IPACMERR("Failed to delete tcp_fin_rst rule \n");
4999 				ret = IPACM_FAILURE;
5000 			}
5001 			return ret;
5002 		}
5003 		else
5004 		{
5005 			wandown_data->backhaul_type = m_is_sta_mode;
5006 			memcpy(wandown_data->ipv6_prefix, ipv6_prefix, sizeof(wandown_data->ipv6_prefix));
5007 			evt_data.event = IPA_HANDLE_WAN_DOWN_V6;
5008 			evt_data.evt_data = (void *)wandown_data;
5009 			/* Insert IPA_HANDLE_WAN_DOWN to command queue */
5010 			IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN for IPv6 with prefix 0x%08x%08x\n", ipv6_prefix[0], ipv6_prefix[1]);
5011 			IPACM_EvtDispatcher::PostEvt(&evt_data);
5012 			IPACMDBG_H("setup wan_up_v6/active_v6= false \n");
5013 			IPACM_Wan::wan_up_v6 = false;
5014 			active_v6 = false;
5015 			if(IPACM_Wan::wan_up)
5016 			{
5017 				IPACMDBG_H("modem v4-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name);
5018 			}
5019 			else
5020 			{
5021 				memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name));
5022 			}
5023 			/* Delete MHI icmpv6 exception rule */
5024 			if(delete_icmpv6_exception_rule())
5025 			{
5026 				IPACMERR("Failed to delete icmpv6 rule \n");
5027 				return IPACM_FAILURE;
5028 			}
5029 
5030 		}
5031 	}
5032 	else
5033 	{
5034 		IPACMDBG_H(" The default WAN routing rules are deleted already \n");
5035 	}
5036 
5037 	return IPACM_SUCCESS;
5038 }
5039 
handle_route_del_evt_ex(ipa_ip_type iptype)5040 int IPACM_Wan::handle_route_del_evt_ex(ipa_ip_type iptype)
5041 {
5042 	ipacm_cmd_q_data evt_data;
5043 #ifdef WAN_IOC_NOTIFY_WAN_STATE
5044 	struct wan_ioctl_notify_wan_state wan_state;
5045 	int fd_wwan_ioctl;
5046 	memset(&wan_state, 0, sizeof(wan_state));
5047 #endif
5048 
5049 	IPACMDBG_H("got handle_route_del_evt_ex with ip-family:%d \n", iptype);
5050 
5051 	if(tx_prop == NULL)
5052 	{
5053 		IPACMDBG_H("No tx properties, ignore delete default route setting\n");
5054 		return IPACM_SUCCESS;
5055 	}
5056 
5057 	is_default_gateway = false;
5058 	IPACMDBG_H("Default route is deleted to iface %s.\n", dev_name);
5059 
5060 	if (((iptype == IPA_IP_v4) && (active_v4 == true)) ||
5061 		((iptype == IPA_IP_v6) && (active_v6 == true)))
5062 	{
5063 		if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_None && IPACM_Iface::ipacmcfg->GetIPAVer() < IPA_HW_v4_0)
5064 		{
5065 			/* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */
5066 			IPACMDBG_H("dev %s delete producer dependency\n", dev_name);
5067 			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]);
5068 			IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
5069 		}
5070 #ifdef WAN_IOC_NOTIFY_WAN_STATE
5071 		else {
5072 			IPACMDBG_H("ipa_pm_q6_check to %d\n", ipa_pm_q6_check);
5073 			if(ipa_pm_q6_check == 1)
5074 			{
5075 				fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
5076 				if(fd_wwan_ioctl < 0)
5077 				{
5078 					IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME);
5079 					return false;
5080 				}
5081 				IPACMDBG_H("send WAN_IOC_NOTIFY_WAN_STATE down to IPA_PM\n");
5082 #ifdef WAN_IOCTL_NOTIFY_WAN_INTF_NAME
5083                                 strlcpy(wan_state.upstreamIface, dev_name, IFNAMSIZ);
5084 #endif
5085 				if(ioctl(fd_wwan_ioctl, WAN_IOC_NOTIFY_WAN_STATE, &wan_state))
5086 				{
5087 					IPACMERR("Failed to send WAN_IOC_NOTIFY_WAN_STATE as up %d\n ", wan_state.up);
5088 				}
5089 				close(fd_wwan_ioctl);
5090 
5091 				/* Store the Offload state. */
5092 				FILE *fp = NULL;
5093 				fp = fopen(IPA_OFFLOAD_TETHER_STATE_FILE_NAME, "w");
5094 				if (fp == NULL)
5095 				{
5096 					IPACMERR("Failed to write offload state to %s, error is %d - %s\n",
5097 						IPA_OFFLOAD_TETHER_STATE_FILE_NAME, errno, strerror(errno));
5098 				}
5099 				else
5100 				{
5101 					fprintf(fp, "UPSTREAM=%s,STATE=DOWN", dev_name);
5102 					fclose(fp);
5103 				}
5104 			}
5105 			if (ipa_pm_q6_check > 0)
5106 				ipa_pm_q6_check--;
5107 			else
5108 				IPACMERR(" ipa_pm_q6_check becomes negative !!!\n");
5109 		}
5110 #endif
5111 		/* Delete the default route*/
5112 		if (iptype == IPA_IP_v6)
5113 		{
5114 			IPACMDBG_H("ip-type %d: default v6 wan RT-rule deleted\n",iptype);
5115 			if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl_a5[0], IPA_IP_v6) == false)
5116 			{
5117 				IPACMDBG_H("IP-family:%d, Routing rule(hdl:0x%x) deletion failed!\n",IPA_IP_v6,wan_route_rule_v6_hdl_a5[0]);
5118 				return IPACM_FAILURE;
5119 			}
5120 		}
5121 
5122 		ipacm_event_iface_up *wandown_data;
5123 		wandown_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up));
5124 		if (wandown_data == NULL)
5125 		{
5126 			IPACMERR("Unable to allocate memory\n");
5127 			return IPACM_FAILURE;
5128 		}
5129 		memset(wandown_data, 0, sizeof(ipacm_event_iface_up));
5130 
5131 		if (iptype == IPA_IP_v4)
5132 		{
5133 			wandown_data->ipv4_addr = wan_v4_addr;
5134 			wandown_data->backhaul_type = m_is_sta_mode;
5135 			evt_data.event = IPA_HANDLE_WAN_DOWN;
5136 			evt_data.evt_data = (void *)wandown_data;
5137 			/* Insert IPA_HANDLE_WAN_DOWN to command queue */
5138 			IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN for IPv4 with address: 0x%x\n", wan_v4_addr);
5139 			IPACM_EvtDispatcher::PostEvt(&evt_data);
5140 
5141 			IPACMDBG_H("setup wan_up/active_v4= false \n");
5142 			IPACM_Wan::wan_up = false;
5143 			active_v4 = false;
5144 			if(IPACM_Wan::wan_up_v6)
5145 			{
5146 				IPACMDBG_H("modem v6-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name);
5147 			}
5148 			else
5149 			{
5150 				memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name));
5151 			}
5152 		}
5153 		else
5154 		{
5155 
5156 			wandown_data->backhaul_type = m_is_sta_mode;
5157 			memcpy(wandown_data->ipv6_prefix, ipv6_prefix, sizeof(wandown_data->ipv6_prefix));
5158 			evt_data.event = IPA_HANDLE_WAN_DOWN_V6;
5159 			evt_data.evt_data = (void *)wandown_data;
5160 			IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN_V6 for IPv6 with prefix 0x%08x%08x\n", ipv6_prefix[0], ipv6_prefix[1]);
5161 			IPACM_EvtDispatcher::PostEvt(&evt_data);
5162 
5163 			IPACMDBG_H("setup wan_up_v6/active_v6= false \n");
5164 			IPACM_Wan::wan_up_v6 = false;
5165 			active_v6 = false;
5166 			if(IPACM_Wan::wan_up)
5167 			{
5168 				IPACMDBG_H("modem v4-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name);
5169 			}
5170 			else
5171 			{
5172 				memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name));
5173 			}
5174 		}
5175 	}
5176 	else
5177 	{
5178 		IPACMDBG_H(" The default WAN routing rules are deleted already \n");
5179 	}
5180 
5181 	return IPACM_SUCCESS;
5182 }
5183 
5184 /* configure the initial embms filter rules */
config_dft_embms_rules(ipa_ioc_add_flt_rule * pFilteringTable_v4,ipa_ioc_add_flt_rule * pFilteringTable_v6)5185 int IPACM_Wan::config_dft_embms_rules(ipa_ioc_add_flt_rule *pFilteringTable_v4, ipa_ioc_add_flt_rule *pFilteringTable_v6)
5186 {
5187 	struct ipa_flt_rule_add flt_rule_entry;
5188 	struct ipa_ioc_get_rt_tbl_indx rt_tbl_idx;
5189 	struct ipa_ioc_generate_flt_eq flt_eq;
5190 
5191 	if (rx_prop == NULL)
5192 	{
5193 		IPACMDBG("No rx properties registered for iface %s\n", dev_name);
5194 		return IPACM_SUCCESS;
5195 	}
5196 
5197 	if(pFilteringTable_v4 == NULL || pFilteringTable_v6 == NULL)
5198 	{
5199 		IPACMERR("Either v4 or v6 filtering table is empty.\n");
5200 		return IPACM_FAILURE;
5201 	}
5202 
5203 	/* set up ipv4 odu rule*/
5204 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
5205 
5206 	/* get eMBMS ODU tbl index*/
5207 	memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
5208 	strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v4.name, IPA_RESOURCE_NAME_MAX);
5209 	rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
5210 	rt_tbl_idx.ip = IPA_IP_v4;
5211 	if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
5212 	{
5213 		IPACMERR("Failed to get routing table index from name\n");
5214 		return IPACM_FAILURE;
5215 	}
5216 	IPACMDBG_H("Odu routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
5217 
5218 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
5219 	flt_rule_entry.flt_rule_hdl = -1;
5220 	flt_rule_entry.status = -1;
5221 	flt_rule_entry.at_rear = false;
5222 
5223 	flt_rule_entry.rule.retain_hdr = 0;
5224 	flt_rule_entry.rule.to_uc = 0;
5225 	flt_rule_entry.rule.eq_attrib_type = 1;
5226 	flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
5227 	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
5228 		flt_rule_entry.rule.hashable = true;
5229 	flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
5230 
5231 	memcpy(&flt_rule_entry.rule.attrib,
5232 				 &rx_prop->rx[0].attrib,
5233 				 sizeof(struct ipa_rule_attrib));
5234 	flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
5235 	flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000;
5236 	flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000;
5237 
5238 	memset(&flt_eq, 0, sizeof(flt_eq));
5239 	memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
5240 	flt_eq.ip = IPA_IP_v4;
5241 	if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
5242 	{
5243 		IPACMERR("Failed to get eq_attrib\n");
5244 		return IPACM_FAILURE;
5245 	}
5246 	memcpy(&flt_rule_entry.rule.eq_attrib,
5247 				 &flt_eq.eq_attrib,
5248 				 sizeof(flt_rule_entry.rule.eq_attrib));
5249 
5250 	memcpy(&(pFilteringTable_v4->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
5251 
5252 	/* construc v6 rule */
5253 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
5254 	/* get eMBMS ODU tbl*/
5255 	memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
5256 	strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v6.name, IPA_RESOURCE_NAME_MAX);
5257 	rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
5258 	rt_tbl_idx.ip = IPA_IP_v6;
5259 	if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
5260 	{
5261 		IPACMERR("Failed to get routing table index from name\n");
5262 		return IPACM_FAILURE;
5263 	}
5264 	IPACMDBG_H("Odu routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
5265 
5266 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
5267 	flt_rule_entry.flt_rule_hdl = -1;
5268 	flt_rule_entry.status = -1;
5269 	flt_rule_entry.at_rear = false;
5270 
5271 	flt_rule_entry.rule.retain_hdr = 0;
5272 	flt_rule_entry.rule.to_uc = 0;
5273 	flt_rule_entry.rule.eq_attrib_type = 1;
5274 	flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
5275 	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
5276 		flt_rule_entry.rule.hashable = true;
5277 	flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
5278 
5279 	memcpy(&flt_rule_entry.rule.attrib,
5280 				 &rx_prop->rx[0].attrib,
5281 				 sizeof(struct ipa_rule_attrib));
5282 	flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
5283 	flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;
5284 	flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
5285 	flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
5286 	flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
5287 	flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000;
5288 	flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
5289 	flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
5290 	flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
5291 
5292 	memset(&flt_eq, 0, sizeof(flt_eq));
5293 	memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
5294 	flt_eq.ip = IPA_IP_v6;
5295 	if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
5296 	{
5297 		IPACMERR("Failed to get eq_attrib\n");
5298 		return IPACM_FAILURE;
5299 	}
5300 	memcpy(&flt_rule_entry.rule.eq_attrib,
5301 				 &flt_eq.eq_attrib,
5302 				 sizeof(flt_rule_entry.rule.eq_attrib));
5303 
5304 	memcpy(&(pFilteringTable_v6->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
5305 
5306 	return IPACM_SUCCESS;
5307 }
5308 
5309 
5310 /*for STA mode: handle wan-iface down event */
handle_down_evt()5311 int IPACM_Wan::handle_down_evt()
5312 {
5313 	int res = IPACM_SUCCESS;
5314 	uint32_t i, tether_total;
5315 	int ipa_if_num_tether_tmp[IPA_MAX_IFACE_ENTRIES];
5316 
5317 	tether_total = 0;
5318 	memset(ipa_if_num_tether_tmp, 0, IPA_MAX_IFACE_ENTRIES);
5319 
5320 	IPACMDBG_H(" wan handle_down_evt \n");
5321 	if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_None && IPACM_Iface::ipacmcfg->GetIPAVer() < IPA_HW_v4_0)
5322 	{
5323 		/* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */
5324 		IPACMDBG_H("dev %s delete producer dependency\n", dev_name);
5325 		if (tx_prop != NULL)
5326 		{
5327 			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]);
5328 			IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
5329 		}
5330 	}
5331 	/* no iface address up, directly close iface*/
5332 	if (ip_type == IPACM_IP_NULL)
5333 	{
5334 		goto fail;
5335 	}
5336 
5337 	/* make sure default routing rules and firewall rules are deleted*/
5338 	if (active_v4)
5339 	{
5340 		if (rx_prop != NULL)
5341 		{
5342 			del_dft_firewall_rules(IPA_IP_v4);
5343 		}
5344 		handle_route_del_evt(IPA_IP_v4);
5345 		IPACMDBG_H("Delete default v4 routing rules\n");
5346 
5347 
5348 #ifdef FEATURE_IPA_ANDROID
5349 		/* posting wan_down_tether for lan clients */
5350 #ifdef FEATURE_IPACM_HAL
5351 		IPACMDBG_H("Posting IPA_WAN_DOWN_TETHER_EVENT for IPV4\n");
5352 		post_wan_down_tether_evt(IPA_IP_v4, 0);
5353 #else
5354 		for (i=0; i < IPACM_Wan::ipa_if_num_tether_v4_total; i++)
5355 		{
5356 			ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v4[i];
5357 		}
5358 		tether_total = IPACM_Wan::ipa_if_num_tether_v4_total;
5359 		for (i=0; i < tether_total; i++)
5360 		{
5361 			post_wan_down_tether_evt(IPA_IP_v4, ipa_if_num_tether_tmp[i]);
5362 			IPACMDBG_H("post_wan_down_tether_v4 iface(%d: %s)\n",
5363 				i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name);
5364 		}
5365 #endif
5366 #endif
5367 	}
5368 
5369 	if (active_v6)
5370 	{
5371 		if (rx_prop != NULL)
5372 		{
5373 			del_dft_firewall_rules(IPA_IP_v6);
5374 		}
5375 		handle_route_del_evt(IPA_IP_v6);
5376 		IPACMDBG_H("Delete default v6 routing rules\n");
5377 
5378 #ifdef FEATURE_IPA_ANDROID
5379 		/* posting wan_down_tether for lan clients */
5380 #ifdef FEATURE_IPACM_HAL
5381 		IPACMDBG_H("Posting IPA_WAN_DOWN_TETHER_EVENT for IPV6\n");
5382 		post_wan_down_tether_evt(IPA_IP_v6, 0);
5383 #else
5384 		for (i=0; i < IPACM_Wan::ipa_if_num_tether_v6_total; i++)
5385 		{
5386 			ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v6[i];
5387 		}
5388 		tether_total = IPACM_Wan::ipa_if_num_tether_v6_total;
5389 		for (i=0; i < tether_total; i++)
5390 		{
5391 			post_wan_down_tether_evt(IPA_IP_v6, ipa_if_num_tether_tmp[i]);
5392 			IPACMDBG_H("post_wan_down_tether_v6 iface(%d: %s)\n",
5393 				i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name);
5394 		}
5395 #endif
5396 #endif
5397 	}
5398 
5399 	/* Delete default v4 RT rule */
5400 	if (ip_type != IPA_IP_v6 && wan_v4_addr_set)
5401 	{
5402 		/* no need delete v4 RSC routing rules */
5403 		IPACMDBG_H("Delete default v4 routing rules\n");
5404 		if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
5405 		{
5406 			IPACMERR("Routing rule deletion failed!\n");
5407 			res = IPACM_FAILURE;
5408 			goto fail;
5409 		}
5410 	}
5411 
5412 	/* delete default v6 RT rule */
5413 	if (ip_type != IPA_IP_v4)
5414 	{
5415 		IPACMDBG_H("Delete default v6 routing rules\n");
5416 		/* May have multiple ipv6 iface-routing rules*/
5417 		for (i = 0; i < 2*num_dft_rt_v6; i++)
5418 		{
5419 			if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
5420 			{
5421 				IPACMERR("Routing rule deletion failed!\n");
5422 				res = IPACM_FAILURE;
5423 				goto fail;
5424 			}
5425 		}
5426 		IPACMDBG_H("finished delete default v6 RT rules\n ");
5427 	}
5428 
5429 	/* check software routing fl rule hdl */
5430 	if (softwarerouting_act == true)
5431 	{
5432 		if(m_is_sta_mode == Q6_MHI_WAN)
5433 		{
5434 			handle_software_routing_disable(true);
5435 		}
5436 		else
5437 		{
5438 			handle_software_routing_disable(false);
5439 		}
5440 	}
5441 
5442 	if(m_is_sta_mode != Q6_MHI_WAN)
5443 	{
5444 		/* clean wan-client header, routing rules */
5445 		IPACMDBG_H("left %d wan clients need to be deleted \n ", num_wan_client);
5446 		for (i = 0; i < num_wan_client; i++)
5447 		{
5448 				/* Del NAT rules before ipv4 RT rules are delete */
5449 				if(get_client_memptr(wan_client, i)->ipv4_set == true)
5450 				{
5451 					IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wan_client, i)->v4_addr);
5452 					CtList->HandleSTAClientDelEvt(get_client_memptr(wan_client, i)->v4_addr);
5453 				}
5454 
5455 				if (delete_wan_rtrules(i, IPA_IP_v4))
5456 				{
5457 					IPACMERR("unbale to delete wan-client v4 route rules for index %d\n", i);
5458 					res = IPACM_FAILURE;
5459 					goto fail;
5460 				}
5461 
5462 				if (delete_wan_rtrules(i, IPA_IP_v6))
5463 				{
5464 					IPACMERR("unbale to delete ecm-client v6 route rules for index %d\n", i);
5465 					res = IPACM_FAILURE;
5466 					goto fail;
5467 				}
5468 
5469 				IPACMDBG_H("Delete %d client header\n", num_wan_client);
5470 				if(get_client_memptr(wan_client, i)->ipv4_header_set == true)
5471 				{
5472 					if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, i)->hdr_hdl_v4)
5473 						== false)
5474 					{
5475 						res = IPACM_FAILURE;
5476 						goto fail;
5477 					}
5478 				}
5479 				if(get_client_memptr(wan_client, i)->ipv6_header_set == true)
5480 				{
5481 					if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, i)->hdr_hdl_v6)
5482 						== false)
5483 					{
5484 						res = IPACM_FAILURE;
5485 						goto fail;
5486 					}
5487 				}
5488 		} /* end of for loop */
5489 		/* free the edm clients cache */
5490 		IPACMDBG_H("Free wan clients cache\n");
5491 
5492 		/* free dft ipv4 filter rule handlers if any */
5493 		if (ip_type != IPA_IP_v6 && rx_prop != NULL)
5494 		{
5495 			if (dft_v4fl_rule_hdl[0] != 0)
5496 			{
5497 				if (m_filtering.DeleteFilteringHdls(dft_v4fl_rule_hdl,
5498 					IPA_IP_v4,
5499 					IPV4_DEFAULT_FILTERTING_RULES) == false)
5500 				{
5501 					IPACMERR("Error Delete Filtering rules, aborting...\n");
5502 					res = IPACM_FAILURE;
5503 					goto fail;
5504 				}
5505 				IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES);
5506 				IPACMDBG_H("finished delete default v4 filtering rules\n ");
5507 			}
5508 		}
5509 		/* free dft ipv6 filter rule handlers if any */
5510 		if (ip_type != IPA_IP_v4 && rx_prop != NULL)
5511 		{
5512 			if (dft_v6fl_rule_hdl[0] != 0)
5513 			{
5514 				if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl,
5515 					IPA_IP_v6,
5516 					IPV6_DEFAULT_FILTERTING_RULES) == false)
5517 				{
5518 					IPACMERR("ErrorDeleting Filtering rule, aborting...\n");
5519 					res = IPACM_FAILURE;
5520 					goto fail;
5521 				}
5522 				IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES);
5523 			}
5524 			if(num_ipv6_dest_flt_rule > 0 && num_ipv6_dest_flt_rule <= MAX_DEFAULT_v6_ROUTE_RULES)
5525 			{
5526 				if(m_filtering.DeleteFilteringHdls(ipv6_dest_flt_rule_hdl,  IPA_IP_v6, num_ipv6_dest_flt_rule) == false)
5527 				{
5528 					IPACMERR("Failed to delete ipv6 dest flt rules.\n");
5529 					res = IPACM_FAILURE;
5530 					goto fail;
5531 				}
5532 				IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, num_ipv6_dest_flt_rule);
5533 			}
5534 			IPACMDBG_H("finished delete default v6 filtering rules\n ");
5535 		}
5536 		if(hdr_proc_hdl_dummy_v6)
5537 		{
5538 			if(m_header.DeleteHeaderProcCtx(hdr_proc_hdl_dummy_v6) == false)
5539 			{
5540 				IPACMERR("Failed to delete hdr_proc_hdl_dummy_v6\n");
5541 				res = IPACM_FAILURE;
5542 				goto fail;
5543 			}
5544 		}
5545 		if(hdr_hdl_dummy_v6)
5546 		{
5547 			if (m_header.DeleteHeaderHdl(hdr_hdl_dummy_v6) == false)
5548 			{
5549 				IPACMERR("Failed to delete hdr_hdl_dummy_v6\n");
5550 				res = IPACM_FAILURE;
5551 				goto fail;
5552 			}
5553 		}
5554 	}
5555 fail:
5556 	if (tx_prop != NULL)
5557 	{
5558 		free(tx_prop);
5559 	}
5560 	if (rx_prop != NULL)
5561 	{
5562 		free(rx_prop);
5563 	}
5564 	if (iface_query != NULL)
5565 	{
5566 		free(iface_query);
5567 	}
5568 	if (wan_route_rule_v4_hdl != NULL)
5569 	{
5570 		free(wan_route_rule_v4_hdl);
5571 	}
5572 	if (wan_route_rule_v6_hdl != NULL)
5573 	{
5574 		free(wan_route_rule_v6_hdl);
5575 	}
5576 	if (wan_route_rule_v6_hdl_a5 != NULL)
5577 	{
5578 		free(wan_route_rule_v6_hdl_a5);
5579 	}
5580 	if (wan_client != NULL)
5581 	{
5582 		free(wan_client);
5583 	}
5584 	close(m_fd_ipa);
5585 	return res;
5586 }
5587 
handle_down_evt_ex()5588 int IPACM_Wan::handle_down_evt_ex()
5589 {
5590 	int res = IPACM_SUCCESS;
5591 	uint32_t i;
5592 #ifndef FEATURE_IPACM_HAL
5593 	uint32_t tether_total;
5594 	int ipa_if_num_tether_tmp[IPA_MAX_IFACE_ENTRIES];
5595 #endif
5596 
5597 	IPACMDBG_H(" wan handle_down_evt \n");
5598 
5599 	/* free ODU filter rule handlers */
5600 	if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == EMBMS_IF)
5601 	{
5602 		embms_is_on = false;
5603 		if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_None && IPACM_Iface::ipacmcfg->GetIPAVer() < IPA_HW_v4_0)
5604 		{
5605 			/* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */
5606 			IPACMDBG_H("dev %s delete producer dependency\n", dev_name);
5607 			if (tx_prop != NULL)
5608 			{
5609 				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]);
5610 				IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
5611 			}
5612 		}
5613 		if (rx_prop != NULL)
5614 		{
5615 			install_wan_filtering_rule(false);
5616 			IPACMDBG("finished delete embms filtering rule\n ");
5617 		}
5618 		goto fail;
5619 	}
5620 
5621 	/* no iface address up, directly close iface*/
5622 	if (ip_type == IPACM_IP_NULL)
5623 	{
5624 		goto fail;
5625 	}
5626 
5627 #ifndef IPA_MTU_EVENT_MAX
5628 	/* reset the mtu size */
5629 	mtu_v4 = DEFAULT_MTU_SIZE;
5630 	mtu_v4_set = false;
5631 	mtu_v6 = DEFAULT_MTU_SIZE;
5632 	mtu_v6_set = false;
5633 #endif
5634 
5635 	if(ip_type == IPA_IP_v4)
5636 	{
5637 		num_ipv4_modem_pdn--;
5638 		IPACMDBG_H("Now the number of ipv4 modem pdn is %d.\n", num_ipv4_modem_pdn);
5639 		/* only when default gw goes down we post WAN_DOWN event*/
5640 		if(is_default_gateway == true)
5641 		{
5642 			IPACM_Wan::wan_up = false;
5643 			del_wan_firewall_rule(IPA_IP_v4);
5644 			install_wan_filtering_rule(false);
5645 			handle_route_del_evt_ex(IPA_IP_v4);
5646 #ifdef FEATURE_IPA_ANDROID
5647 			/* posting wan_down_tether for all lan clients */
5648 #ifdef FEATURE_IPACM_HAL
5649 			post_wan_down_tether_evt(IPA_IP_v4, 0);
5650 #else
5651 			for (i=0; i < IPACM_Wan::ipa_if_num_tether_v4_total; i++)
5652 			{
5653 				ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v4[i];
5654 			}
5655 			tether_total = IPACM_Wan::ipa_if_num_tether_v4_total;
5656 			for (i=0; i < tether_total; i++)
5657 			{
5658 				post_wan_down_tether_evt(IPA_IP_v4, ipa_if_num_tether_tmp[i]);
5659 				IPACMDBG_H("post_wan_down_tether_v4 iface(%d: %s)\n",
5660 					i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name);
5661 			}
5662 #endif
5663 #endif
5664 			if(IPACM_Wan::wan_up_v6)
5665 			{
5666 				IPACMDBG_H("modem v6-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name);
5667 			}
5668 			else
5669 			{
5670 				memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name));
5671 			}
5672 		}
5673 
5674 		/* only when the last ipv4 modem interface goes down, delete ipv4 default flt rules*/
5675 		if(num_ipv4_modem_pdn == 0)
5676 		{
5677 			IPACMDBG_H("Now the number of modem ipv4 interface is 0, delete default flt rules.\n");
5678 		IPACM_Wan::num_v4_flt_rule = 0;
5679 		memset(IPACM_Wan::flt_rule_v4, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
5680 		install_wan_filtering_rule(false);
5681 		}
5682 
5683 		IPACMDBG_H("Delete default v4 coalesce routing rules\n");
5684 		if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[0], IPA_IP_v4) == false)
5685 		{
5686 			IPACMERR("Routing rule RSC TCP deletion failed!\n");
5687 			res = IPACM_FAILURE;
5688 			goto fail;
5689 		}
5690 
5691 		if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[1], IPA_IP_v4) == false)
5692 		{
5693 			IPACMERR("Routing rule RSB UDP deletion failed!\n");
5694 			res = IPACM_FAILURE;
5695 			goto fail;
5696 		}
5697 
5698 		if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
5699 		{
5700 			IPACMERR("Routing rule deletion failed!\n");
5701 			res = IPACM_FAILURE;
5702 			goto fail;
5703 		}
5704 	}
5705 	else if(ip_type == IPA_IP_v6)
5706 	{
5707 	    if (num_dft_rt_v6 > 1)
5708 			num_ipv6_modem_pdn--;
5709 		IPACMDBG_H("Now the number of ipv6 modem pdn is %d.\n", num_ipv6_modem_pdn);
5710 		/* only when default gw goes down we post WAN_DOWN event*/
5711 		if(is_default_gateway == true)
5712 		{
5713 			IPACM_Wan::wan_up_v6 = false;
5714 			del_wan_firewall_rule(IPA_IP_v6);
5715 			install_wan_filtering_rule(false);
5716 			handle_route_del_evt_ex(IPA_IP_v6);
5717 #ifdef FEATURE_IPA_ANDROID
5718 			/* posting wan_down_tether for all lan clients */
5719 #ifdef FEATURE_IPACM_HAL
5720 			post_wan_down_tether_evt(IPA_IP_v6, 0);
5721 #else
5722 			for (i=0; i < IPACM_Wan::ipa_if_num_tether_v6_total; i++)
5723 			{
5724 				ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v6[i];
5725 			}
5726 			tether_total = IPACM_Wan::ipa_if_num_tether_v6_total;
5727 			for (i=0; i < tether_total; i++)
5728 			{
5729 				post_wan_down_tether_evt(IPA_IP_v6, ipa_if_num_tether_tmp[i]);
5730 				IPACMDBG_H("post_wan_down_tether_v6 iface(%d: %s)\n",
5731 					i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name);
5732 			}
5733 #endif
5734 #endif
5735 			if(IPACM_Wan::wan_up)
5736 			{
5737 				IPACMDBG_H("modem v4-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name);
5738 			}
5739 			else
5740 			{
5741 				memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name));
5742 			}
5743 		}
5744 
5745 		/* only when the last ipv6 modem interface goes down, delete ipv6 default flt rules*/
5746 		if(num_ipv6_modem_pdn == 0)
5747 		{
5748 			IPACMDBG_H("Now the number of modem ipv6 interface is 0, delete default flt rules.\n");
5749 		IPACM_Wan::num_v6_flt_rule = 0;
5750 		memset(IPACM_Wan::flt_rule_v6, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
5751 		install_wan_filtering_rule(false);
5752 		}
5753 
5754 		for (i = 0; i < 2*num_dft_rt_v6; i++)
5755 		{
5756 			/* delete v6 colasce rules */
5757 			if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
5758 			{
5759 				IPACMERR("Colasce Routing rule deletion failed!\n");
5760 				res = IPACM_FAILURE;
5761 				goto fail;
5762 			}
5763 			if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
5764 			{
5765 				IPACMERR("Routing rule deletion failed!\n");
5766 				res = IPACM_FAILURE;
5767 				goto fail;
5768 			}
5769 		}
5770 	}
5771 	else
5772 	{
5773 		num_ipv4_modem_pdn--;
5774 		IPACMDBG_H("Now the number of ipv4 modem pdn is %d.\n", num_ipv4_modem_pdn);
5775 	    if (num_dft_rt_v6 > 1)
5776 			num_ipv6_modem_pdn--;
5777 		IPACMDBG_H("Now the number of ipv6 modem pdn is %d.\n", num_ipv6_modem_pdn);
5778 		/* only when default gw goes down we post WAN_DOWN event*/
5779 		if(is_default_gateway == true)
5780 		{
5781 			IPACM_Wan::wan_up = false;
5782 			del_wan_firewall_rule(IPA_IP_v4);
5783 			handle_route_del_evt_ex(IPA_IP_v4);
5784 #ifdef FEATURE_IPA_ANDROID
5785 			/* posting wan_down_tether for all lan clients */
5786 #ifdef FEATURE_IPACM_HAL
5787 			IPACMDBG_H("Posting IPA_WAN_DOWN_TETHER_EVENT for IPV4\n");
5788 			post_wan_down_tether_evt(IPA_IP_v4, 0);
5789 #else
5790 			for (i=0; i < IPACM_Wan::ipa_if_num_tether_v4_total; i++)
5791 			{
5792 				ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v4[i];
5793 			}
5794 			tether_total = IPACM_Wan::ipa_if_num_tether_v4_total;
5795 			for (i=0; i < tether_total; i++)
5796 			{
5797 				post_wan_down_tether_evt(IPA_IP_v4, ipa_if_num_tether_tmp[i]);
5798 				IPACMDBG_H("post_wan_down_tether_v4 iface(%d: %s)\n",
5799 					i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name);
5800 			}
5801 #endif
5802 #endif
5803 			IPACM_Wan::wan_up_v6 = false;
5804 			del_wan_firewall_rule(IPA_IP_v6);
5805 			handle_route_del_evt_ex(IPA_IP_v6);
5806 #ifdef FEATURE_IPA_ANDROID
5807 			/* posting wan_down_tether for all lan clients */
5808 #ifdef FEATURE_IPACM_HAL
5809                         IPACMDBG_H("Posting IPA_WAN_DOWN_TETHER_EVENT for IPV6\n");
5810                         post_wan_down_tether_evt(IPA_IP_v6, 0);
5811 #else
5812 			for (i=0; i < IPACM_Wan::ipa_if_num_tether_v6_total; i++)
5813 			{
5814 				ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v6[i];
5815 			}
5816 			tether_total = IPACM_Wan::ipa_if_num_tether_v6_total;
5817 			for (i=0; i < tether_total; i++)
5818 			{
5819 				post_wan_down_tether_evt(IPA_IP_v6, ipa_if_num_tether_tmp[i]);
5820 				IPACMDBG_H("post_wan_down_tether_v6 iface(%d: %s)\n",
5821 					i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name);
5822 			}
5823 #endif
5824 #endif
5825 			memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name));
5826 
5827 			install_wan_filtering_rule(false);
5828 		}
5829 
5830 		/* only when the last ipv4 modem interface goes down, delete ipv4 default flt rules*/
5831 		if(num_ipv4_modem_pdn == 0)
5832 		{
5833 			IPACMDBG_H("Now the number of modem ipv4 interface is 0, delete default flt rules.\n");
5834 			IPACM_Wan::num_v4_flt_rule = 0;
5835 			memset(IPACM_Wan::flt_rule_v4, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
5836 			install_wan_filtering_rule(false);
5837 		}
5838 		/* only when the last ipv6 modem interface goes down, delete ipv6 default flt rules*/
5839 		if(num_ipv6_modem_pdn == 0)
5840 		{
5841 			IPACMDBG_H("Now the number of modem ipv6 interface is 0, delete default flt rules.\n");
5842 			IPACM_Wan::num_v6_flt_rule = 0;
5843 			memset(IPACM_Wan::flt_rule_v6, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
5844 			install_wan_filtering_rule(false);
5845 		}
5846 
5847 		IPACMDBG_H("Delete default v4 coalesce routing rules\n");
5848 		if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[0], IPA_IP_v4) == false)
5849 		{
5850 			IPACMERR("Routing rule RSC TCP deletion failed!\n");
5851 			res = IPACM_FAILURE;
5852 			goto fail;
5853 		}
5854 
5855 		if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[1], IPA_IP_v4) == false)
5856 		{
5857 			IPACMERR("Routing rule RSB UDP deletion failed!\n");
5858 			res = IPACM_FAILURE;
5859 			goto fail;
5860 		}
5861 
5862 		if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
5863 		{
5864 			IPACMERR("Routing rule deletion failed!\n");
5865 			res = IPACM_FAILURE;
5866 			goto fail;
5867 		}
5868 
5869 		for (i = 0; i < 2*num_dft_rt_v6; i++)
5870 		{
5871 			/* delete v6 colasce rules */
5872 			if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
5873 			{
5874 				IPACMERR("Colasce Routing rule deletion failed!\n");
5875 				res = IPACM_FAILURE;
5876 				goto fail;
5877 			}
5878 			if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
5879 			{
5880 				IPACMERR("Routing rule deletion failed!\n");
5881 				res = IPACM_FAILURE;
5882 				goto fail;
5883 			}
5884 		}
5885 	}
5886 
5887 //	/* check software routing fl rule hdl */
5888 //	if (softwarerouting_act == true)
5889 //	{
5890 //		handle_software_routing_disable();
5891 //	}
5892 
5893 fail:
5894 	if (tx_prop != NULL)
5895 	{
5896 		free(tx_prop);
5897 	}
5898 	if (rx_prop != NULL)
5899 	{
5900 		free(rx_prop);
5901 	}
5902 	if (ext_prop != NULL)
5903 	{
5904 		free(ext_prop);
5905 	}
5906 	if (iface_query != NULL)
5907 	{
5908 		free(iface_query);
5909 	}
5910 	if (wan_route_rule_v4_hdl != NULL)
5911 	{
5912 		free(wan_route_rule_v4_hdl);
5913 	}
5914 	if (wan_route_rule_v6_hdl != NULL)
5915 	{
5916 		free(wan_route_rule_v6_hdl);
5917 	}
5918 	if (wan_route_rule_v6_hdl_a5 != NULL)
5919 	{
5920 		free(wan_route_rule_v6_hdl_a5);
5921 	}
5922 	if (wan_client != NULL)
5923 	{
5924 		free(wan_client);
5925 	}
5926 	close(m_fd_ipa);
5927 	return res;
5928 }
5929 
install_wan_filtering_rule(bool is_sw_routing)5930 int IPACM_Wan::install_wan_filtering_rule(bool is_sw_routing)
5931 {
5932 	int len, res = IPACM_SUCCESS;
5933 	uint8_t mux_id;
5934 	ipa_ioc_add_flt_rule *pFilteringTable_v4 = NULL;
5935 	ipa_ioc_add_flt_rule *pFilteringTable_v6 = NULL;
5936 
5937 	mux_id = IPACM_Iface::ipacmcfg->GetQmapId();
5938 	if(rx_prop == NULL)
5939 	{
5940 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
5941 		return IPACM_SUCCESS;
5942 	}
5943 	if (is_sw_routing == true ||
5944 			IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true)
5945 	{
5946 		/* contruct SW-RT rules to Q6*/
5947 		struct ipa_flt_rule_add flt_rule_entry;
5948 		struct ipa_ioc_get_rt_tbl_indx rt_tbl_idx;
5949 		ipa_ioc_generate_flt_eq flt_eq;
5950 
5951 		IPACMDBG("\n");
5952 		if (softwarerouting_act == true)
5953 		{
5954 			IPACMDBG("already setup software_routing rule for (%s)iface ip-family %d\n",
5955 								IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ip_type);
5956 			return IPACM_SUCCESS;
5957 		}
5958 
5959 		len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add);
5960 		pFilteringTable_v4 = (struct ipa_ioc_add_flt_rule*)malloc(len);
5961 		if (pFilteringTable_v4 == NULL)
5962 		{
5963 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
5964 			return IPACM_FAILURE;
5965 		}
5966 		memset(pFilteringTable_v4, 0, len);
5967 		IPACMDBG_H("Total number of WAN DL filtering rule for IPv4 is 1\n");
5968 
5969 		pFilteringTable_v4->commit = 1;
5970 		pFilteringTable_v4->ep = rx_prop->rx[0].src_pipe;
5971 		pFilteringTable_v4->global = false;
5972 		pFilteringTable_v4->ip = IPA_IP_v4;
5973 		pFilteringTable_v4->num_rules = (uint8_t)1;
5974 
5975 		/* Configuring Software-Routing Filtering Rule */
5976 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
5977 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
5978 		strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
5979 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
5980 		rt_tbl_idx.ip = IPA_IP_v4;
5981 		if(ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx) < 0)
5982 		{
5983 			IPACMERR("Failed to get routing table index from name\n");
5984 			res = IPACM_FAILURE;
5985 			goto fail;
5986 		}
5987 		IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
5988 
5989 		flt_rule_entry.at_rear = false;
5990 		flt_rule_entry.flt_rule_hdl = -1;
5991 		flt_rule_entry.status = -1;
5992 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
5993 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
5994 			flt_rule_entry.rule.hashable = true;
5995 
5996 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
5997 
5998 		memcpy(&flt_rule_entry.rule.attrib,
5999 					&rx_prop->rx[0].attrib,
6000 					sizeof(flt_rule_entry.rule.attrib));
6001 		flt_rule_entry.rule.retain_hdr = 0;
6002 		flt_rule_entry.rule.to_uc = 0;
6003 		flt_rule_entry.rule.eq_attrib_type = 1;
6004 
6005 		memset(&flt_eq, 0, sizeof(flt_eq));
6006 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
6007 		flt_eq.ip = IPA_IP_v4;
6008 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
6009 		{
6010 			IPACMERR("Failed to get eq_attrib\n");
6011 			res = IPACM_FAILURE;
6012 			goto fail;
6013 		}
6014 		memcpy(&flt_rule_entry.rule.eq_attrib,
6015 			&flt_eq.eq_attrib,
6016 			sizeof(flt_rule_entry.rule.eq_attrib));
6017 		memcpy(&(pFilteringTable_v4->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
6018 
6019 		len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add);
6020 		pFilteringTable_v6 = (struct ipa_ioc_add_flt_rule*)malloc(len);
6021 		if (pFilteringTable_v6 == NULL)
6022 		{
6023 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
6024 			free(pFilteringTable_v4);
6025 			return IPACM_FAILURE;
6026 		}
6027 		memset(pFilteringTable_v6, 0, len);
6028 		IPACMDBG_H("Total number of WAN DL filtering rule for IPv6 is 1\n");
6029 
6030 		pFilteringTable_v6->commit = 1;
6031 		pFilteringTable_v6->ep = rx_prop->rx[0].src_pipe;
6032 		pFilteringTable_v6->global = false;
6033 		pFilteringTable_v6->ip = IPA_IP_v6;
6034 		pFilteringTable_v6->num_rules = (uint8_t)1;
6035 
6036 		/* Configuring Software-Routing Filtering Rule */
6037 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
6038 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
6039 		strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
6040 		rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
6041 		rt_tbl_idx.ip = IPA_IP_v6;
6042 		if(ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx) < 0)
6043 		{
6044 			IPACMERR("Failed to get routing table index from name\n");
6045 			res = IPACM_FAILURE;
6046 			goto fail;
6047 		}
6048 		IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
6049 
6050 		flt_rule_entry.at_rear = false;
6051 		flt_rule_entry.flt_rule_hdl = -1;
6052 		flt_rule_entry.status = -1;
6053 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
6054 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
6055 			flt_rule_entry.rule.hashable = true;
6056 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
6057 		memcpy(&flt_rule_entry.rule.attrib,
6058 					&rx_prop->rx[0].attrib,
6059 					sizeof(flt_rule_entry.rule.attrib));
6060 		flt_rule_entry.rule.retain_hdr = 0;
6061 		flt_rule_entry.rule.to_uc = 0;
6062 		flt_rule_entry.rule.eq_attrib_type = 1;
6063 
6064 		memset(&flt_eq, 0, sizeof(flt_eq));
6065 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
6066 		flt_eq.ip = IPA_IP_v6;
6067 		if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
6068 		{
6069 			IPACMERR("Failed to get eq_attrib\n");
6070 			res = IPACM_FAILURE;
6071 			goto fail;
6072 		}
6073 		memcpy(&flt_rule_entry.rule.eq_attrib,
6074 			&flt_eq.eq_attrib,
6075 			sizeof(flt_rule_entry.rule.eq_attrib));
6076 		memcpy(&(pFilteringTable_v6->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
6077 		softwarerouting_act = true;
6078 		/* end of contruct SW-RT rules to Q6*/
6079 	}
6080 	else
6081 	{
6082 		if(embms_is_on == false)
6083 		{
6084 			if(IPACM_Wan::num_v4_flt_rule > 0)
6085 			{
6086 				len = sizeof(struct ipa_ioc_add_flt_rule) + IPACM_Wan::num_v4_flt_rule * sizeof(struct ipa_flt_rule_add);
6087 				pFilteringTable_v4 = (struct ipa_ioc_add_flt_rule*)malloc(len);
6088 
6089 				IPACMDBG_H("Total number of WAN DL filtering rule for IPv4 is %d\n", IPACM_Wan::num_v4_flt_rule);
6090 
6091 				if (pFilteringTable_v4 == NULL)
6092 				{
6093 					IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
6094 					return IPACM_FAILURE;
6095 				}
6096 				memset(pFilteringTable_v4, 0, len);
6097 				pFilteringTable_v4->commit = 1;
6098 				pFilteringTable_v4->ep = rx_prop->rx[0].src_pipe;
6099 				pFilteringTable_v4->global = false;
6100 				pFilteringTable_v4->ip = IPA_IP_v4;
6101 				pFilteringTable_v4->num_rules = (uint8_t)IPACM_Wan::num_v4_flt_rule;
6102 
6103 				memcpy(pFilteringTable_v4->rules, IPACM_Wan::flt_rule_v4, IPACM_Wan::num_v4_flt_rule * sizeof(ipa_flt_rule_add));
6104 			}
6105 
6106 			if(IPACM_Wan::num_v6_flt_rule > 0)
6107 			{
6108 				len = sizeof(struct ipa_ioc_add_flt_rule) + IPACM_Wan::num_v6_flt_rule * sizeof(struct ipa_flt_rule_add);
6109 				pFilteringTable_v6 = (struct ipa_ioc_add_flt_rule*)malloc(len);
6110 
6111 				IPACMDBG_H("Total number of WAN DL filtering rule for IPv6 is %d\n", IPACM_Wan::num_v6_flt_rule);
6112 
6113 				if (pFilteringTable_v6 == NULL)
6114 				{
6115 					IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
6116 					free(pFilteringTable_v4);
6117 					return IPACM_FAILURE;
6118 				}
6119 				memset(pFilteringTable_v6, 0, len);
6120 				pFilteringTable_v6->commit = 1;
6121 				pFilteringTable_v6->ep = rx_prop->rx[0].src_pipe;
6122 				pFilteringTable_v6->global = false;
6123 				pFilteringTable_v6->ip = IPA_IP_v6;
6124 				pFilteringTable_v6->num_rules = (uint8_t)IPACM_Wan::num_v6_flt_rule;
6125 
6126 				memcpy(pFilteringTable_v6->rules, IPACM_Wan::flt_rule_v6, IPACM_Wan::num_v6_flt_rule * sizeof(ipa_flt_rule_add));
6127 			}
6128 		}
6129 		else	//embms is on, always add 1 embms rule on top of WAN DL flt table
6130 		{
6131 			/* allocate ipv4 filtering table */
6132 			len = sizeof(struct ipa_ioc_add_flt_rule) + (1 + IPACM_Wan::num_v4_flt_rule) * sizeof(struct ipa_flt_rule_add);
6133 			pFilteringTable_v4 = (struct ipa_ioc_add_flt_rule*)malloc(len);
6134 			IPACMDBG_H("Total number of WAN DL filtering rule for IPv4 is %d\n", IPACM_Wan::num_v4_flt_rule + 1);
6135 			if (pFilteringTable_v4 == NULL)
6136 			{
6137 				IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
6138 				return IPACM_FAILURE;
6139 			}
6140 			memset(pFilteringTable_v4, 0, len);
6141 			pFilteringTable_v4->commit = 1;
6142 			pFilteringTable_v4->ep = rx_prop->rx[0].src_pipe;
6143 			pFilteringTable_v4->global = false;
6144 			pFilteringTable_v4->ip = IPA_IP_v4;
6145 			pFilteringTable_v4->num_rules = (uint8_t)IPACM_Wan::num_v4_flt_rule + 1;
6146 
6147 			/* allocate ipv6 filtering table */
6148 			len = sizeof(struct ipa_ioc_add_flt_rule) + (1 + IPACM_Wan::num_v6_flt_rule) * sizeof(struct ipa_flt_rule_add);
6149 			pFilteringTable_v6 = (struct ipa_ioc_add_flt_rule*)malloc(len);
6150 			IPACMDBG_H("Total number of WAN DL filtering rule for IPv6 is %d\n", IPACM_Wan::num_v6_flt_rule + 1);
6151 			if (pFilteringTable_v6 == NULL)
6152 			{
6153 				IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
6154 				free(pFilteringTable_v4);
6155 				return IPACM_FAILURE;
6156 			}
6157 			memset(pFilteringTable_v6, 0, len);
6158 			pFilteringTable_v6->commit = 1;
6159 			pFilteringTable_v6->ep = rx_prop->rx[0].src_pipe;
6160 			pFilteringTable_v6->global = false;
6161 			pFilteringTable_v6->ip = IPA_IP_v6;
6162 			pFilteringTable_v6->num_rules = (uint8_t)IPACM_Wan::num_v6_flt_rule + 1;
6163 
6164 			config_dft_embms_rules(pFilteringTable_v4, pFilteringTable_v6);
6165 			if(IPACM_Wan::num_v4_flt_rule > 0)
6166 			{
6167 				memcpy(&(pFilteringTable_v4->rules[1]), IPACM_Wan::flt_rule_v4, IPACM_Wan::num_v4_flt_rule * sizeof(ipa_flt_rule_add));
6168 			}
6169 
6170 			if(IPACM_Wan::num_v6_flt_rule > 0)
6171 			{
6172 				memcpy(&(pFilteringTable_v6->rules[1]), IPACM_Wan::flt_rule_v6, IPACM_Wan::num_v6_flt_rule * sizeof(ipa_flt_rule_add));
6173 			}
6174 		}
6175 	}
6176 
6177 	if(false == m_filtering.AddWanDLFilteringRule(pFilteringTable_v4, pFilteringTable_v6, mux_id))
6178 	{
6179 		IPACMERR("Failed to install WAN DL filtering table.\n");
6180 		res = IPACM_FAILURE;
6181 		goto fail;
6182 	}
6183 
6184 fail:
6185 	if(pFilteringTable_v4 != NULL)
6186 	{
6187 		free(pFilteringTable_v4);
6188 	}
6189 	if(pFilteringTable_v6 != NULL)
6190 	{
6191 		free(pFilteringTable_v6);
6192 	}
6193 	return res;
6194 }
6195 
6196 /* handle STA WAN-client */
6197 /* handle WAN client initial, construct full headers (tx property) */
handle_wan_hdr_init(uint8_t * mac_addr,bool replaced,int entry)6198 int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr, bool replaced, int entry)
6199 {
6200 
6201 #define WAN_IFACE_INDEX_LEN 2
6202 
6203 	int res = IPACM_SUCCESS, len = 0;
6204 	char index[WAN_IFACE_INDEX_LEN];
6205 	struct ipa_ioc_copy_hdr sCopyHeader;
6206 	struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL;
6207 	uint32_t cnt;
6208 	int clnt_indx;
6209 
6210 	IPACMDBG_H("WAN client number: %d\n", num_wan_client);
6211 
6212 	if(!replaced)
6213 	{
6214 		clnt_indx = get_wan_client_index(mac_addr);
6215 
6216 		if (clnt_indx != IPACM_INVALID_INDEX)
6217 		{
6218 			IPACMERR("eth client is found/attached already with index %d \n", clnt_indx);
6219 			return IPACM_FAILURE;
6220 		}
6221 
6222 		/* add header to IPA */
6223 		if (num_wan_client >= IPA_MAX_NUM_WAN_CLIENTS)
6224 		{
6225 			IPACMERR("Reached maximum number(%d) of eth clients\n", IPA_MAX_NUM_WAN_CLIENTS);
6226 			return IPACM_FAILURE;
6227 		}
6228 
6229 		memcpy(get_client_memptr(wan_client, num_wan_client)->mac,
6230 				 mac_addr,
6231 				 sizeof(get_client_memptr(wan_client, num_wan_client)->mac));
6232 
6233 		IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
6234 					 mac_addr[0], mac_addr[1], mac_addr[2],
6235 					 mac_addr[3], mac_addr[4], mac_addr[5]);
6236 
6237 		IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
6238 					 get_client_memptr(wan_client, num_wan_client)->mac[0],
6239 					 get_client_memptr(wan_client, num_wan_client)->mac[1],
6240 					 get_client_memptr(wan_client, num_wan_client)->mac[2],
6241 					 get_client_memptr(wan_client, num_wan_client)->mac[3],
6242 					 get_client_memptr(wan_client, num_wan_client)->mac[4],
6243 					 get_client_memptr(wan_client, num_wan_client)->mac[5]);
6244 	}
6245 
6246 	/* add header to IPA */
6247 	if(tx_prop != NULL)
6248 	{
6249 		len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add));
6250 		pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len);
6251 		if (pHeaderDescriptor == NULL)
6252 		{
6253 			IPACMERR("calloc failed to allocate pHeaderDescriptor\n");
6254 			return IPACM_FAILURE;
6255 		}
6256 
6257 		/* copy partial header for v4*/
6258 		for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
6259 		{
6260 				 if(tx_prop->tx[cnt].ip==IPA_IP_v4)
6261 				 {
6262 								IPACMDBG_H("Got partial v4-header name from %d tx props\n", cnt);
6263 								memset(&sCopyHeader, 0, sizeof(sCopyHeader));
6264 								memcpy(sCopyHeader.name,
6265 											 tx_prop->tx[cnt].hdr_name,
6266 											 sizeof(sCopyHeader.name));
6267 
6268 								IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt);
6269 								if (m_header.CopyHeader(&sCopyHeader) == false)
6270 								{
6271 									PERROR("ioctl copy header failed");
6272 									res = IPACM_FAILURE;
6273 									goto fail;
6274 								}
6275 
6276 								IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
6277 								IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst);
6278 								if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE)
6279 								{
6280 									IPACMERR("header oversize\n");
6281 									res = IPACM_FAILURE;
6282 									goto fail;
6283 								}
6284 								else
6285 								{
6286 									memcpy(pHeaderDescriptor->hdr[0].hdr,
6287 												 sCopyHeader.hdr,
6288 												 sCopyHeader.hdr_len);
6289 								}
6290 
6291 								/* copy client mac_addr to partial header */
6292 								IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n",
6293 										sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst);
6294 
6295 								/* only copy 6 bytes mac-address */
6296 								if(sCopyHeader.is_eth2_ofst_valid == false)
6297 								{
6298 									memcpy(&pHeaderDescriptor->hdr[0].hdr[0],
6299 											mac_addr, IPA_MAC_ADDR_SIZE);
6300 								}
6301 								else
6302 								{
6303 									memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst],
6304 											mac_addr, IPA_MAC_ADDR_SIZE);
6305 								}
6306 
6307 
6308 								pHeaderDescriptor->commit = true;
6309 								pHeaderDescriptor->num_hdrs = 1;
6310 
6311 								memset(pHeaderDescriptor->hdr[0].name, 0,
6312 											 sizeof(pHeaderDescriptor->hdr[0].name));
6313 
6314 								snprintf(index,sizeof(index), "%d", ipa_if_num);
6315 								strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name));
6316 								pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0';
6317 								if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_WAN_PARTIAL_HDR_NAME_v4, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX)
6318 								{
6319 									IPACMERR(" header name construction failed exceed length (%zu)\n", strlen(pHeaderDescriptor->hdr[0].name));
6320 									res = IPACM_FAILURE;
6321 									goto fail;
6322 								}
6323 
6324 								snprintf(index,sizeof(index), "%d", header_name_count);
6325 								if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX)
6326 								{
6327 									IPACMERR(" header name construction failed exceed length (%zu)\n", strlen(pHeaderDescriptor->hdr[0].name));
6328 									res = IPACM_FAILURE;
6329 									goto fail;
6330 								}
6331 
6332 								pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len;
6333 								pHeaderDescriptor->hdr[0].hdr_hdl = -1;
6334 								pHeaderDescriptor->hdr[0].is_partial = 0;
6335 								pHeaderDescriptor->hdr[0].status = -1;
6336 
6337 					 if (m_header.AddHeader(pHeaderDescriptor) == false ||
6338 							pHeaderDescriptor->hdr[0].status != 0)
6339 					 {
6340 						IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status);
6341 						res = IPACM_FAILURE;
6342 						goto fail;
6343 					 }
6344 
6345 					if (!replaced)
6346 					{
6347 						get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl;
6348 						IPACMDBG_H("eth-client(%d) v4 full header name:%s header handle:(0x%x)\n",
6349 												 num_wan_client,
6350 												 pHeaderDescriptor->hdr[0].name,
6351 												 get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v4);
6352 									get_client_memptr(wan_client, num_wan_client)->ipv4_header_set=true;
6353 					} else
6354 					{
6355 						get_client_memptr(wan_client, entry)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl;
6356 						IPACMDBG_H("replaced eth-client(%d) v4 full header name:%s header handle:(0x%x)\n",
6357 												 entry,
6358 												 pHeaderDescriptor->hdr[0].name,
6359 												 get_client_memptr(wan_client, entry)->hdr_hdl_v4);
6360 									get_client_memptr(wan_client, entry)->ipv4_header_set=true;
6361 					}
6362 					break;
6363 				 }
6364 		}
6365 
6366 
6367 		/* copy partial header for v6*/
6368 		for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
6369 		{
6370 			if(tx_prop->tx[cnt].ip==IPA_IP_v6)
6371 			{
6372 
6373 				IPACMDBG_H("Got partial v6-header name from %d tx props\n", cnt);
6374 				memset(&sCopyHeader, 0, sizeof(sCopyHeader));
6375 				memcpy(sCopyHeader.name,
6376 						tx_prop->tx[cnt].hdr_name,
6377 							sizeof(sCopyHeader.name));
6378 
6379 				IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt);
6380 				if (m_header.CopyHeader(&sCopyHeader) == false)
6381 				{
6382 					PERROR("ioctl copy header failed");
6383 					res = IPACM_FAILURE;
6384 					goto fail;
6385 				}
6386 
6387 				IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
6388 				IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst);
6389 				if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE)
6390 				{
6391 					IPACMERR("header oversize\n");
6392 					res = IPACM_FAILURE;
6393 					goto fail;
6394 				}
6395 				else
6396 				{
6397 					memcpy(pHeaderDescriptor->hdr[0].hdr,
6398 							sCopyHeader.hdr,
6399 							sCopyHeader.hdr_len);
6400 				}
6401 
6402 				/* copy client mac_addr to partial header */
6403 				if(sCopyHeader.is_eth2_ofst_valid == false)
6404 				{
6405 					memcpy(&pHeaderDescriptor->hdr[0].hdr[0],
6406 								 mac_addr, IPA_MAC_ADDR_SIZE); /* only copy 6 bytes mac-address */
6407 				}
6408 				else
6409 				{
6410 					memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst],
6411 								 mac_addr, IPA_MAC_ADDR_SIZE); /* only copy 6 bytes mac-address */
6412 				}
6413 
6414 
6415 				pHeaderDescriptor->commit = true;
6416 				pHeaderDescriptor->num_hdrs = 1;
6417 
6418 				memset(pHeaderDescriptor->hdr[0].name, 0,
6419 					 sizeof(pHeaderDescriptor->hdr[0].name));
6420 
6421 				snprintf(index,sizeof(index), "%d", ipa_if_num);
6422 				strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name));
6423 				pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0';
6424 				if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_WAN_PARTIAL_HDR_NAME_v6, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX)
6425 				{
6426 					IPACMERR(" header name construction failed exceed length (%zu)\n", strlen(pHeaderDescriptor->hdr[0].name));
6427 					res = IPACM_FAILURE;
6428 					goto fail;
6429 				}
6430 				snprintf(index,sizeof(index), "%d", header_name_count);
6431 				if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX)
6432 				{
6433 					IPACMERR(" header name construction failed exceed length (%zu)\n", strlen(pHeaderDescriptor->hdr[0].name));
6434 					res = IPACM_FAILURE;
6435 					goto fail;
6436 				}
6437 
6438 				pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len;
6439 				pHeaderDescriptor->hdr[0].hdr_hdl = -1;
6440 				pHeaderDescriptor->hdr[0].is_partial = 0;
6441 				pHeaderDescriptor->hdr[0].status = -1;
6442 
6443 				if (m_header.AddHeader(pHeaderDescriptor) == false ||
6444 						pHeaderDescriptor->hdr[0].status != 0)
6445 				{
6446 					IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status);
6447 					res = IPACM_FAILURE;
6448 					goto fail;
6449 				}
6450 
6451 				if (!replaced)
6452 				{
6453 					get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl;
6454 					IPACMDBG_H("eth-client(%d) v6 full header name:%s header handle:(0x%x)\n",
6455 						 num_wan_client,
6456 						 pHeaderDescriptor->hdr[0].name,
6457 									 get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v6);
6458 									get_client_memptr(wan_client, num_wan_client)->ipv6_header_set=true;
6459 				}
6460 				else
6461 				{
6462 					get_client_memptr(wan_client, entry)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl;
6463 					IPACMDBG_H("replaced eth-client(%d) v6 full header name:%s header handle:(0x%x)\n",
6464 							entry,
6465 							pHeaderDescriptor->hdr[0].name,
6466 							get_client_memptr(wan_client, entry)->hdr_hdl_v6);
6467 							get_client_memptr(wan_client, entry)->ipv6_header_set=true;
6468 				}
6469 
6470 				break;
6471 
6472 			}
6473 		}
6474 		/* initialize wifi client*/
6475 		if (!replaced)
6476 		{
6477 			get_client_memptr(wan_client, num_wan_client)->route_rule_set_v4 = false;
6478 			get_client_memptr(wan_client, num_wan_client)->route_rule_set_v6 = 0;
6479 			get_client_memptr(wan_client, num_wan_client)->ipv4_set = false;
6480 			get_client_memptr(wan_client, num_wan_client)->ipv6_set = 0;
6481 			num_wan_client++;
6482 		}
6483 		else
6484 		{
6485 			get_client_memptr(wan_client, entry)->route_rule_set_v4 = false;
6486 			get_client_memptr(wan_client, entry)->route_rule_set_v6 = 0;
6487 			get_client_memptr(wan_client, entry)->ipv4_set = false;
6488 			get_client_memptr(wan_client, entry)->ipv6_set = 0;
6489 		}
6490 		header_name_count++; //keep increasing header_name_count
6491 		res = IPACM_SUCCESS;
6492 		IPACMDBG_H("eth client number: %d\n", num_wan_client);
6493 	}
6494 	else
6495 	{
6496 		return res;
6497 	}
6498 fail:
6499 	free(pHeaderDescriptor);
6500 
6501 	return res;
6502 }
6503 
6504 /*handle eth client */
handle_wan_client_ipaddr(ipacm_event_data_all * data)6505 int IPACM_Wan::handle_wan_client_ipaddr(ipacm_event_data_all *data)
6506 {
6507 	int clnt_indx;
6508 	int v6_num;
6509 
6510 	IPACMDBG_H("number of wan clients: %d\n", num_wan_client);
6511 	IPACMDBG_H(" event MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
6512 					 data->mac_addr[0],
6513 					 data->mac_addr[1],
6514 					 data->mac_addr[2],
6515 					 data->mac_addr[3],
6516 					 data->mac_addr[4],
6517 					 data->mac_addr[5]);
6518 
6519 	clnt_indx = get_wan_client_index(data->mac_addr);
6520 
6521 		if (clnt_indx == IPACM_INVALID_INDEX)
6522 		{
6523 			IPACMERR("wan client not found/attached \n");
6524 			return IPACM_FAILURE;
6525 		}
6526 
6527 	IPACMDBG_H("Ip-type received %d\n", data->iptype);
6528 	if (data->iptype == IPA_IP_v4)
6529 	{
6530 		IPACMDBG_H("ipv4 address: 0x%x\n", data->ipv4_addr);
6531 		if (data->ipv4_addr != 0) /* not 0.0.0.0 */
6532 		{
6533 			if (get_client_memptr(wan_client, clnt_indx)->ipv4_set == false)
6534 			{
6535 				get_client_memptr(wan_client, clnt_indx)->v4_addr = data->ipv4_addr;
6536 				get_client_memptr(wan_client, clnt_indx)->ipv4_set = true;
6537 				/* Add NAT rules after ipv4 RT rules are set */
6538 				CtList->HandleSTAClientAddEvt(data->ipv4_addr);
6539 			}
6540 			else
6541 			{
6542 			   /* check if client got new IPv4 address*/
6543 			   if(data->ipv4_addr == get_client_memptr(wan_client, clnt_indx)->v4_addr)
6544 			   {
6545 			     IPACMDBG_H("Already setup ipv4 addr for client:%d, ipv4 address didn't change\n", clnt_indx);
6546 				 return IPACM_FAILURE;
6547 			   }
6548 			   else
6549 			   {
6550 					IPACMDBG_H("ipv4 addr for client:%d is changed \n", clnt_indx);
6551 					/* Del NAT rules before ipv4 RT rules are delete */
6552 					CtList->HandleSTAClientDelEvt(get_client_memptr(wan_client, clnt_indx)->v4_addr);
6553 					delete_wan_rtrules(clnt_indx,IPA_IP_v4);
6554 					get_client_memptr(wan_client, clnt_indx)->route_rule_set_v4 = false;
6555 					get_client_memptr(wan_client, clnt_indx)->v4_addr = data->ipv4_addr;
6556 					/* Add NAT rules after ipv4 RT rules are set */
6557 					CtList->HandleSTAClientAddEvt(data->ipv4_addr);
6558 				}
6559 			}
6560 		}
6561 		else
6562 		{
6563 				IPACMDBG_H("Invalid client IPv4 address \n");
6564 				return IPACM_FAILURE;
6565 		}
6566 	}
6567 	else
6568 	{
6569 		if ((data->ipv6_addr[0] != 0) || (data->ipv6_addr[1] != 0) ||
6570 				(data->ipv6_addr[2] != 0) || (data->ipv6_addr[3] != 0)) /* check if all 0 not valid ipv6 address */
6571 		{
6572 		   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]);
6573                    if(get_client_memptr(wan_client, clnt_indx)->ipv6_set < IPV6_NUM_ADDR)
6574 		   {
6575 
6576 		       for(v6_num=0;v6_num < get_client_memptr(wan_client, clnt_indx)->ipv6_set;v6_num++)
6577 	               {
6578 			      if( data->ipv6_addr[0] == get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][0] &&
6579 			           data->ipv6_addr[1] == get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][1] &&
6580 			  	        data->ipv6_addr[2]== get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][2] &&
6581 			  	         data->ipv6_addr[3] == get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][3])
6582 			      {
6583 			  	    IPACMDBG_H("Already see this ipv6 addr for client:%d\n", clnt_indx);
6584 			  	    return IPACM_FAILURE; /* not setup the RT rules*/
6585 			      }
6586 		       }
6587 
6588 		       /* not see this ipv6 before for wifi client*/
6589 			   get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][0] = data->ipv6_addr[0];
6590 			   get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][1] = data->ipv6_addr[1];
6591 			   get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][2] = data->ipv6_addr[2];
6592 			   get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][3] = data->ipv6_addr[3];
6593 			   get_client_memptr(wan_client, clnt_indx)->ipv6_set++;
6594 		    }
6595 		    else
6596 		    {
6597 		         IPACMDBG_H("Already got 3 ipv6 addr for client:%d\n", clnt_indx);
6598 			 return IPACM_FAILURE; /* not setup the RT rules*/
6599 		    }
6600 		}
6601 		else
6602 		{
6603 			IPACMDBG_H("Invalid IPV6 address\n");
6604 			return IPACM_FAILURE;
6605 		}
6606 	}
6607 
6608 	return IPACM_SUCCESS;
6609 }
6610 
6611 /*handle wan client routing rule*/
handle_wan_client_route_rule(uint8_t * mac_addr,ipa_ip_type iptype)6612 int IPACM_Wan::handle_wan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype)
6613 {
6614 	struct ipa_ioc_add_rt_rule *rt_rule;
6615 	struct ipa_rt_rule_add *rt_rule_entry;
6616 	uint32_t tx_index;
6617 	int wan_index,v6_num;
6618 	const int NUM = 1;
6619 
6620 	if(tx_prop == NULL)
6621 	{
6622 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
6623 		return IPACM_SUCCESS;
6624 	}
6625 
6626 	IPACMDBG_H("Received mac_addr MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
6627 			mac_addr[0], mac_addr[1], mac_addr[2],
6628 			mac_addr[3], mac_addr[4], mac_addr[5]);
6629 
6630 	wan_index = get_wan_client_index(mac_addr);
6631 	if (wan_index == IPACM_INVALID_INDEX)
6632 	{
6633 		IPACMDBG_H("wan client not found/attached \n");
6634 		return IPACM_SUCCESS;
6635 	}
6636 
6637 	if (iptype==IPA_IP_v4) {
6638 		IPACMDBG_H("wan client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", wan_index, iptype,
6639 				get_client_memptr(wan_client, wan_index)->ipv4_set,
6640 				get_client_memptr(wan_client, wan_index)->route_rule_set_v4);
6641 	} else {
6642 		IPACMDBG_H("wan client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", wan_index, iptype,
6643 				get_client_memptr(wan_client, wan_index)->ipv6_set,
6644 				get_client_memptr(wan_client, wan_index)->route_rule_set_v6);
6645 	}
6646 
6647 	/* Add default routing rules if not set yet */
6648 	if ((iptype == IPA_IP_v4
6649 				&& get_client_memptr(wan_client, wan_index)->route_rule_set_v4 == false
6650 				&& get_client_memptr(wan_client, wan_index)->ipv4_set == true)
6651 			|| (iptype == IPA_IP_v6
6652 				&& get_client_memptr(wan_client, wan_index)->route_rule_set_v6 < get_client_memptr(wan_client, wan_index)->ipv6_set
6653 			   ))
6654 	{
6655 		if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_None && IPACM_Iface::ipacmcfg->GetIPAVer() < IPA_HW_v4_0)
6656 		{
6657 			/* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */
6658 			IPACMDBG_H("dev %s add producer dependency\n", dev_name);
6659 			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]);
6660 			IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false);
6661 		}
6662 		rt_rule = (struct ipa_ioc_add_rt_rule *)
6663 			calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
6664 					NUM * sizeof(struct ipa_rt_rule_add));
6665 
6666 		if (rt_rule == NULL)
6667 		{
6668 			PERROR("Error Locate ipa_ioc_add_rt_rule memory...\n");
6669 			return IPACM_FAILURE;
6670 		}
6671 
6672 		rt_rule->commit = 1;
6673 		rt_rule->num_rules = (uint8_t)NUM;
6674 		rt_rule->ip = iptype;
6675 
6676 		for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
6677 		{
6678 			if(iptype != tx_prop->tx[tx_index].ip)
6679 			{
6680 				IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n",
6681 						tx_index, tx_prop->tx[tx_index].ip,iptype);
6682 				continue;
6683 			}
6684 
6685 			rt_rule_entry = &rt_rule->rules[0];
6686 			rt_rule_entry->at_rear = 0;
6687 
6688 			if (iptype == IPA_IP_v4)
6689 			{
6690 				IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", wan_index,
6691 						get_client_memptr(wan_client, wan_index)->v4_addr);
6692 
6693 				IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n",
6694 						wan_index,
6695 						get_client_memptr(wan_client, wan_index)->hdr_hdl_v4);
6696 				strlcpy(rt_rule->rt_tbl_name,
6697 						IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name,
6698 						sizeof(rt_rule->rt_tbl_name));
6699 				rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0';
6700 				if (IPACM_Iface::ipacmcfg->isMCC_Mode == true)
6701 				{
6702 					IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
6703 							tx_prop->tx[tx_index].alt_dst_pipe);
6704 					rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
6705 				}
6706 				else
6707 				{
6708 					rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
6709 				}
6710 				memcpy(&rt_rule_entry->rule.attrib,
6711 						&tx_prop->tx[tx_index].attrib,
6712 						sizeof(rt_rule_entry->rule.attrib));
6713 				rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
6714 				rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, wan_index)->hdr_hdl_v4;
6715 				rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wan_client, wan_index)->v4_addr;
6716 				rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
6717 				if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
6718 					rt_rule_entry->rule.hashable = true;
6719 				if (false == m_routing.AddRoutingRule(rt_rule))
6720 				{
6721 					IPACMERR("Routing rule addition failed!\n");
6722 					free(rt_rule);
6723 					return IPACM_FAILURE;
6724 				}
6725 
6726 				/* copy ipv4 RT hdl */
6727 				get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4 =
6728 					rt_rule->rules[0].rt_rule_hdl;
6729 				IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index,
6730 						get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4, iptype);
6731 			} else {
6732 
6733 				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++)
6734 				{
6735 					IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n",
6736 							wan_index,
6737 							get_client_memptr(wan_client, wan_index)->hdr_hdl_v6);
6738 
6739 					/* v6 LAN_RT_TBL */
6740 					strlcpy(rt_rule->rt_tbl_name,
6741 							IPACM_Iface::ipacmcfg->rt_tbl_v6.name,
6742 							sizeof(rt_rule->rt_tbl_name));
6743 					rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0';
6744 					/* Uplink going to wan clients should go to IPA */
6745 					if (IPACM_Iface::ipacmcfg->isMCC_Mode == true)
6746 					{
6747 						IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
6748 								tx_prop->tx[tx_index].alt_dst_pipe);
6749 						rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
6750 					}
6751 					else
6752 					{
6753 						rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
6754 					}
6755 					memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib));
6756 					rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, wan_index)->hdr_hdl_v6;;
6757 					rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
6758 					rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][0];
6759 					rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][1];
6760 					rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][2];
6761 					rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][3];
6762 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
6763 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
6764 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
6765 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
6766 					if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
6767 						rt_rule_entry->rule.hashable = true;
6768 					if (false == m_routing.AddRoutingRule(rt_rule))
6769 					{
6770 						IPACMERR("Routing rule addition failed!\n");
6771 						free(rt_rule);
6772 						return IPACM_FAILURE;
6773 					}
6774 
6775 					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;
6776 					IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index,
6777 							get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6[v6_num], iptype);
6778 
6779 					/*Copy same rule to v6 WAN RT TBL*/
6780 					strlcpy(rt_rule->rt_tbl_name,
6781 							IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name,
6782 							sizeof(rt_rule->rt_tbl_name));
6783 					rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0';
6784 					/* Downlink traffic from Wan clients, should go exception */
6785 					rt_rule_entry->rule.dst = iface_query->excp_pipe;
6786 					memcpy(&rt_rule_entry->rule.attrib,
6787 							&tx_prop->tx[tx_index].attrib,
6788 							sizeof(rt_rule_entry->rule.attrib));
6789 					rt_rule_entry->rule.hdr_hdl = 0;
6790 					rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
6791 					rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][0];
6792 					rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][1];
6793 					rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][2];
6794 					rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][3];
6795 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
6796 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
6797 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
6798 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
6799 					if (false == m_routing.AddRoutingRule(rt_rule))
6800 					{
6801 						IPACMERR("Routing rule addition failed!\n");
6802 						free(rt_rule);
6803 						return IPACM_FAILURE;
6804 					}
6805 
6806 					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;
6807 					IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index,
6808 							get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num], iptype);
6809 				}
6810 			}
6811 
6812 		} /* end of for loop */
6813 
6814 		free(rt_rule);
6815 
6816 		if (iptype == IPA_IP_v4)
6817 		{
6818 			get_client_memptr(wan_client, wan_index)->route_rule_set_v4 = true;
6819 		}
6820 		else
6821 		{
6822 			get_client_memptr(wan_client, wan_index)->route_rule_set_v6 = get_client_memptr(wan_client, wan_index)->ipv6_set;
6823 		}
6824 	}
6825 
6826 	return IPACM_SUCCESS;
6827 }
6828 
6829 /* TODO Handle wan client routing rules also */
handle_wlan_SCC_MCC_switch(bool isSCCMode,ipa_ip_type iptype)6830 void IPACM_Wan::handle_wlan_SCC_MCC_switch(bool isSCCMode, ipa_ip_type iptype)
6831 {
6832 	struct ipa_ioc_mdfy_rt_rule *rt_rule = NULL;
6833 	struct ipa_rt_rule_mdfy *rt_rule_entry;
6834 	uint32_t tx_index = 0;
6835 
6836 	IPACMDBG("\n");
6837 	if (tx_prop == NULL || is_default_gateway == false)
6838 	{
6839 		IPACMDBG_H("No tx properties or no default route set yet\n");
6840 		return;
6841 	}
6842 
6843 	const int NUM = tx_prop->num_tx_props;
6844 
6845 	for (tx_index = 0; tx_index < tx_prop->num_tx_props; tx_index++)
6846 	{
6847 		if (tx_prop->tx[tx_index].ip != iptype)
6848 		{
6849 			IPACMDBG_H("Tx:%d, ip-type: %d ip-type not matching: %d Ignore\n",
6850 					tx_index, tx_prop->tx[tx_index].ip, iptype);
6851 			continue;
6852 		}
6853 
6854 		if (rt_rule == NULL)
6855 		{
6856 			rt_rule = (struct ipa_ioc_mdfy_rt_rule *)
6857 				calloc(1, sizeof(struct ipa_ioc_mdfy_rt_rule) +
6858 						NUM * sizeof(struct ipa_rt_rule_mdfy));
6859 
6860 			if (rt_rule == NULL)
6861 			{
6862 				IPACMERR("Unable to allocate memory for modify rt rule\n");
6863 				return;
6864 			}
6865 			IPACMDBG("Allocated memory for %d rules successfully\n", NUM);
6866 
6867 			rt_rule->commit = 1;
6868 			rt_rule->num_rules = 0;
6869 			rt_rule->ip = iptype;
6870 		}
6871 
6872 		rt_rule_entry = &rt_rule->rules[rt_rule->num_rules];
6873 
6874 		memcpy(&rt_rule_entry->rule.attrib,
6875 				&tx_prop->tx[tx_index].attrib,
6876 				sizeof(rt_rule_entry->rule.attrib));
6877 		rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
6878 
6879 		if (iptype == IPA_IP_v4)
6880 		{
6881 			rt_rule_entry->rule.attrib.u.v4.dst_addr      = 0;
6882 			rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0;
6883 			rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v4;
6884 			rt_rule_entry->rt_rule_hdl = wan_route_rule_v4_hdl[tx_index];
6885 		}
6886 		else
6887 		{
6888 			rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0;
6889 			rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0;
6890 			rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0;
6891 			rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0;
6892 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0;
6893 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0;
6894 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0;
6895 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0;
6896 
6897 			rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v6;
6898 			rt_rule_entry->rt_rule_hdl = wan_route_rule_v6_hdl[tx_index];
6899 		}
6900 		IPACMDBG_H("Header handle: 0x%x\n", rt_rule_entry->rule.hdr_hdl);
6901 
6902 		if (isSCCMode)
6903 		{
6904 			rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
6905 		}
6906 		else
6907 		{
6908 			IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
6909 					tx_prop->tx[tx_index].alt_dst_pipe);
6910 			rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
6911 		}
6912 
6913 		rt_rule->num_rules++;
6914 	}
6915 
6916 	if (rt_rule != NULL)
6917 	{
6918 
6919 		if (rt_rule->num_rules > 0)
6920 		{
6921 			if (false == m_routing.ModifyRoutingRule(rt_rule))
6922 			{
6923 				IPACMERR("Routing rule modify failed!\n");
6924 				free(rt_rule);
6925 				return;
6926 			}
6927 
6928 			IPACMDBG("Routing rule modified successfully \n");
6929 		}
6930 
6931 		free(rt_rule);
6932 	}
6933 
6934 	return;
6935 }
6936 
handle_wan_client_SCC_MCC_switch(bool isSCCMode,ipa_ip_type iptype)6937 void IPACM_Wan::handle_wan_client_SCC_MCC_switch(bool isSCCMode, ipa_ip_type iptype)
6938 {
6939 	struct ipa_ioc_mdfy_rt_rule *rt_rule = NULL;
6940 	struct ipa_rt_rule_mdfy *rt_rule_entry;
6941 
6942 	uint32_t tx_index = 0, clnt_index =0;
6943 	int v6_num = 0;
6944 	const int NUM_RULES = 1;
6945 
6946 	int size = sizeof(struct ipa_ioc_mdfy_rt_rule) +
6947 		NUM_RULES * sizeof(struct ipa_rt_rule_mdfy);
6948 
6949 	IPACMDBG("isSCCMode: %d\n",isSCCMode);
6950 
6951 	if (tx_prop == NULL || is_default_gateway == false)
6952 	{
6953 		IPACMDBG_H("No tx properties or no default route set yet\n");
6954 		return;
6955 	}
6956 
6957 	rt_rule = (struct ipa_ioc_mdfy_rt_rule *)calloc(1, size);
6958 	if (rt_rule == NULL)
6959 	{
6960 		IPACMERR("Unable to allocate memory for modify rt rule\n");
6961 		return;
6962 	}
6963 
6964 
6965 	for (clnt_index = 0; clnt_index < num_wan_client; clnt_index++)
6966 	{
6967 		if (iptype == IPA_IP_v4)
6968 		{
6969 			IPACMDBG_H("wan client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n",
6970 					clnt_index, iptype,
6971 					get_client_memptr(wan_client, clnt_index)->ipv4_set,
6972 					get_client_memptr(wan_client, clnt_index)->route_rule_set_v4);
6973 
6974 			if( get_client_memptr(wan_client, clnt_index)->route_rule_set_v4 == false ||
6975 					get_client_memptr(wan_client, clnt_index)->ipv4_set == false)
6976 			{
6977 				continue;
6978 			}
6979 
6980 			for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
6981 			{
6982 				if (iptype != tx_prop->tx[tx_index].ip)
6983 				{
6984 					IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d skip\n",
6985 							tx_index, tx_prop->tx[tx_index].ip, iptype);
6986 					continue;
6987 				}
6988 
6989 				memset(rt_rule, 0, size);
6990 				rt_rule->commit = 1;
6991 				rt_rule->num_rules = NUM_RULES;
6992 				rt_rule->ip = iptype;
6993 				rt_rule_entry = &rt_rule->rules[0];
6994 
6995 				IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", clnt_index,
6996 						get_client_memptr(wan_client, clnt_index)->v4_addr);
6997 
6998 				IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n",
6999 						clnt_index,
7000 						get_client_memptr(wan_client, clnt_index)->hdr_hdl_v4);
7001 
7002 				if (IPACM_Iface::ipacmcfg->isMCC_Mode == true)
7003 				{
7004 					IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
7005 							tx_prop->tx[tx_index].alt_dst_pipe);
7006 					rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
7007 				}
7008 				else
7009 				{
7010 					rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
7011 				}
7012 
7013 				memcpy(&rt_rule_entry->rule.attrib,
7014 						&tx_prop->tx[tx_index].attrib,
7015 						sizeof(rt_rule_entry->rule.attrib));
7016 				rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
7017 
7018 				rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, clnt_index)->hdr_hdl_v4;
7019 				rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wan_client, clnt_index)->v4_addr;
7020 				rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
7021 
7022 				/* copy ipv4 RT rule hdl */
7023 				IPACMDBG_H("rt rule hdl=%x\n",
7024 						get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4);
7025 
7026 				rt_rule_entry->rt_rule_hdl =
7027 					get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4;
7028 
7029 				if (false == m_routing.ModifyRoutingRule(rt_rule))
7030 				{
7031 					IPACMERR("Routing rule modify failed!\n");
7032 					free(rt_rule);
7033 					return;
7034 				}
7035 			}
7036 		}
7037 		else
7038 		{
7039 			IPACMDBG_H("wan client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", clnt_index, iptype,
7040 					get_client_memptr(wan_client, clnt_index)->ipv6_set,
7041 					get_client_memptr(wan_client, clnt_index)->route_rule_set_v6);
7042 
7043 			if( get_client_memptr(wan_client, clnt_index)->route_rule_set_v6 == 0)
7044 			{
7045 				continue;
7046 			}
7047 
7048 			for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
7049 			{
7050 				if (iptype != tx_prop->tx[tx_index].ip)
7051 				{
7052 					IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d skip\n",
7053 							tx_index, tx_prop->tx[tx_index].ip, iptype);
7054 					continue;
7055 				}
7056 
7057 				memset(rt_rule, 0, size);
7058 				rt_rule->commit = 1;
7059 				rt_rule->num_rules = NUM_RULES;
7060 				rt_rule->ip = iptype;
7061 				rt_rule_entry = &rt_rule->rules[0];
7062 
7063 				/* Modify only rules in v6 WAN RT TBL*/
7064 				for (v6_num = 0;
7065 						v6_num < get_client_memptr(wan_client, clnt_index)->route_rule_set_v6;
7066 						v6_num++)
7067 				{
7068 					IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n",
7069 							clnt_index,
7070 							get_client_memptr(wan_client, clnt_index)->hdr_hdl_v6);
7071 
7072 					/* Downlink traffic from Wan iface, directly through IPA */
7073 					if (IPACM_Iface::ipacmcfg->isMCC_Mode == true)
7074 					{
7075 						IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
7076 								tx_prop->tx[tx_index].alt_dst_pipe);
7077 						rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
7078 					}
7079 					else
7080 					{
7081 						rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
7082 					}
7083 
7084 					memcpy(&rt_rule_entry->rule.attrib,
7085 							&tx_prop->tx[tx_index].attrib,
7086 							sizeof(rt_rule_entry->rule.attrib));
7087 
7088 					rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, clnt_index)->hdr_hdl_v6;
7089 					rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
7090 					rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][0];
7091 					rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][1];
7092 					rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][2];
7093 					rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][3];
7094 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
7095 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
7096 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
7097 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
7098 
7099 					IPACMDBG_H("rt rule hdl=%x\n",
7100 							get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num]);
7101 
7102 					rt_rule_entry->rt_rule_hdl =
7103 						get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num];
7104 
7105 					if (false == m_routing.ModifyRoutingRule(rt_rule))
7106 					{
7107 						IPACMERR("Routing rule Modify failed!\n");
7108 						free(rt_rule);
7109 						return;
7110 					}
7111 				}
7112 			} /* end of for loop */
7113 		}
7114 
7115 	}
7116 
7117 	free(rt_rule);
7118 	return;
7119 }
7120 
7121 /*handle eth client */
handle_network_stats_update(ipa_get_apn_data_stats_resp_msg_v01 * data)7122 int IPACM_Wan::handle_network_stats_update(ipa_get_apn_data_stats_resp_msg_v01 *data)
7123 {
7124 	FILE *fp = NULL;
7125 
7126 	for (uint32_t apn_index =0; apn_index < data->apn_data_stats_list_len; apn_index++)
7127 	{
7128 		if(data->apn_data_stats_list[apn_index].mux_id == ext_prop->ext[0].mux_id)
7129 		{
7130 			IPACMDBG_H("Received IPA_TETHERING_STATS_UPDATE_NETWORK_STATS, MUX ID %d TX (P%llu/B%llu) RX (P%llu/B%llu)\n",
7131 				data->apn_data_stats_list[apn_index].mux_id,
7132 					(long long)data->apn_data_stats_list[apn_index].num_ul_packets,
7133 						(long long)data->apn_data_stats_list[apn_index].num_ul_bytes,
7134 							(long long)data->apn_data_stats_list[apn_index].num_dl_packets,
7135 								(long long)data->apn_data_stats_list[apn_index].num_dl_bytes);
7136 			fp = fopen(IPA_NETWORK_STATS_FILE_NAME, "w");
7137 			if ( fp == NULL )
7138 			{
7139 				IPACMERR("Failed to write pipe stats to %s, error is %d - %s\n",
7140 						IPA_NETWORK_STATS_FILE_NAME, errno, strerror(errno));
7141 				return IPACM_FAILURE;
7142 			}
7143 
7144 			fprintf(fp, NETWORK_STATS,
7145 				dev_name,
7146 					(long long)data->apn_data_stats_list[apn_index].num_ul_packets,
7147 						(long long)data->apn_data_stats_list[apn_index].num_ul_bytes,
7148 							(long long)data->apn_data_stats_list[apn_index].num_dl_packets,
7149 								(long long)data->apn_data_stats_list[apn_index].num_dl_bytes);
7150 			fclose(fp);
7151 			break;
7152 		};
7153 	}
7154 	return IPACM_SUCCESS;
7155 }
7156 
add_dummy_rx_hdr()7157 int IPACM_Wan::add_dummy_rx_hdr()
7158 {
7159 
7160 #define IFACE_INDEX_LEN 2
7161 	char index[IFACE_INDEX_LEN];
7162 	struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL;
7163 	int len = 0;
7164 	struct ipa_ioc_copy_hdr sCopyHeader;
7165 	struct ipa_hdr_add *ipv6_hdr;
7166 	struct ethhdr *eth_ipv6;
7167 	struct ipa_ioc_add_hdr_proc_ctx* pHeaderProcTable = NULL;
7168 	uint32_t cnt;
7169 
7170 	/* get netdev-mac */
7171 	if(tx_prop != NULL)
7172 	{
7173 		/* copy partial header for v6 */
7174 		for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
7175 		{
7176 				 if(tx_prop->tx[cnt].ip==IPA_IP_v6)
7177 				 {
7178 								IPACMDBG_H("Got partial v6-header name from %d tx props\n", cnt);
7179 								memset(&sCopyHeader, 0, sizeof(sCopyHeader));
7180 								memcpy(sCopyHeader.name,
7181 											 tx_prop->tx[cnt].hdr_name,
7182 											 sizeof(sCopyHeader.name));
7183 
7184 								IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt);
7185 								if (m_header.CopyHeader(&sCopyHeader) == false)
7186 								{
7187 									PERROR("ioctl copy header failed");
7188 									return IPACM_FAILURE;
7189 								}
7190 
7191 								IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
7192 								IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst);
7193 								if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE)
7194 								{
7195 									IPACMERR("header oversize\n");
7196 									return IPACM_FAILURE;
7197 								}
7198 								else
7199 								{
7200 									/* copy client mac_addr to partial header */
7201 									IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n",
7202 											sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst);
7203 									/* only copy 6 bytes mac-address */
7204 									if(sCopyHeader.is_eth2_ofst_valid == false)
7205 									{
7206 										memcpy(netdev_mac, &sCopyHeader.hdr[0+IPA_MAC_ADDR_SIZE],
7207 												sizeof(netdev_mac));
7208 									}
7209 									else
7210 									{
7211 										memcpy(netdev_mac, &sCopyHeader.hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE],
7212 												sizeof(netdev_mac));
7213 									}
7214 								}
7215 					break;
7216 				}
7217 		}
7218 	}
7219 
7220 	len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add));
7221 	pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len);
7222 	if (pHeaderDescriptor == NULL)
7223 	{
7224 		IPACMERR("calloc failed to allocate pHeaderDescriptor\n");
7225 		return IPACM_FAILURE;
7226 	}
7227 	ipv6_hdr = &pHeaderDescriptor->hdr[0];
7228 	/* copy ethernet type to header */
7229 	eth_ipv6 = (struct ethhdr *) (ipv6_hdr->hdr +2);
7230 	memcpy(eth_ipv6->h_dest, netdev_mac, ETH_ALEN);
7231 	memcpy(eth_ipv6->h_source, ext_router_mac_addr, ETH_ALEN);
7232 	eth_ipv6->h_proto = htons(ETH_P_IPV6);
7233 	pHeaderDescriptor->commit = true;
7234 	pHeaderDescriptor->num_hdrs = 1;
7235 
7236 	memset(ipv6_hdr->name, 0,
7237 			 sizeof(pHeaderDescriptor->hdr[0].name));
7238 
7239 	snprintf(index,sizeof(index), "%d", ipa_if_num);
7240 	strlcpy(ipv6_hdr->name, index, sizeof(ipv6_hdr->name));
7241 	ipv6_hdr->name[IPA_RESOURCE_NAME_MAX-1] = '\0';
7242 
7243 	if (strlcat(ipv6_hdr->name, IPA_DUMMY_ETH_HDR_NAME_v6, sizeof(ipv6_hdr->name)) > IPA_RESOURCE_NAME_MAX)
7244 	{
7245 		IPACMERR(" header name construction failed exceed length (%zu)\n", strlen(ipv6_hdr->name));
7246 		return IPACM_FAILURE;
7247 	}
7248 
7249 	ipv6_hdr->hdr_len = ETH_HLEN + 2;
7250 	ipv6_hdr->hdr_hdl = -1;
7251 	ipv6_hdr->is_partial = 0;
7252 	ipv6_hdr->status = -1;
7253 	ipv6_hdr->type = IPA_HDR_L2_ETHERNET_II;
7254 
7255 	if (m_header.AddHeader(pHeaderDescriptor) == false ||
7256 			ipv6_hdr->status != 0)
7257 	{
7258 		IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", ipv6_hdr->status);
7259 		return IPACM_FAILURE;
7260 	}
7261 
7262 	hdr_hdl_dummy_v6 = ipv6_hdr->hdr_hdl;
7263 	IPACMDBG_H("dummy v6 full header name:%s header handle:(0x%x)\n",
7264 								 ipv6_hdr->name,
7265 								 hdr_hdl_dummy_v6);
7266 	/* add dummy hdr_proc_hdl */
7267 	len = sizeof(struct ipa_ioc_add_hdr_proc_ctx) + sizeof(struct ipa_hdr_proc_ctx_add);
7268 	pHeaderProcTable = (ipa_ioc_add_hdr_proc_ctx*)malloc(len);
7269 	if(pHeaderProcTable == NULL)
7270 	{
7271 		IPACMERR("Cannot allocate header processing table.\n");
7272 		return IPACM_FAILURE;
7273 	}
7274 
7275 	memset(pHeaderProcTable, 0, len);
7276 	pHeaderProcTable->commit = 1;
7277 	pHeaderProcTable->num_proc_ctxs = 1;
7278 	pHeaderProcTable->proc_ctx[0].hdr_hdl = hdr_hdl_dummy_v6;
7279 	if (m_header.AddHeaderProcCtx(pHeaderProcTable) == false)
7280 	{
7281 		IPACMERR("Adding dummy hhdr_proc_hdl failed with status: %d\n", pHeaderProcTable->proc_ctx[0].status);
7282 		return IPACM_FAILURE;
7283 	}
7284 	else
7285 	{
7286 		hdr_proc_hdl_dummy_v6 = pHeaderProcTable->proc_ctx[0].proc_ctx_hdl;
7287 		IPACMDBG_H("dummy hhdr_proc_hdl is added successfully. (0x%x)\n", hdr_proc_hdl_dummy_v6);
7288 	}
7289 	return IPACM_SUCCESS;
7290 }
7291 
handle_coalesce_evt()7292 int IPACM_Wan::handle_coalesce_evt()
7293 {
7294 	struct ipa_ioc_add_rt_rule *rt_rule = NULL;
7295 	struct ipa_rt_rule_add *rt_rule_entry;
7296 	const int NUM_RULES = 1;
7297 	int res = IPACM_SUCCESS;
7298 	struct ipa_ioc_get_hdr hdr;
7299 	uint32_t i;
7300 
7301 	if(wan_v4_addr_set)
7302 	{
7303 		/* Delete default RSC v4 RT rule */
7304 		if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[0], IPA_IP_v4) == false)
7305 		{
7306 			IPACMERR("Routing old RSC TCP RT rule deletion failed!\n");
7307 			return  IPACM_FAILURE;
7308 		}
7309 		if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[1], IPA_IP_v4) == false)
7310 		{
7311 			IPACMERR("Routing old RSB UDP RT rule deletion failed!\n");
7312 			return  IPACM_FAILURE;
7313 		}
7314 		/* Delete default v4 RT rule */
7315 		IPACMDBG_H("Delete default v4 routing rules\n");
7316 		if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
7317 		{
7318 			IPACMERR("Routing old RT rule deletion failed!\n");
7319 			return  IPACM_FAILURE;
7320 		}
7321 
7322 		/* apply the new coalesce configuration */
7323 		rt_rule = (struct ipa_ioc_add_rt_rule *)
7324 			 calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
7325 							NUM_RULES * sizeof(struct ipa_rt_rule_add));
7326 		if (!rt_rule)
7327 		{
7328 			IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n");
7329 			return IPACM_FAILURE;
7330 		}
7331 		rt_rule->commit = 1;
7332 		rt_rule->num_rules = NUM_RULES;
7333 		rt_rule->ip = IPA_IP_v4;
7334 		rt_rule_entry = &rt_rule->rules[0];
7335 		rt_rule_entry->at_rear = false;
7336 		rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
7337 		/* still need setup v4 default routing rule to APPs*/
7338 		strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name));
7339 		rt_rule_entry->rule.attrib.u.v4.dst_addr = wan_v4_addr;
7340 		rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
7341 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
7342 			rt_rule_entry->rule.hashable = false;
7343 		/* query qmap header*/
7344 		memset(&hdr, 0, sizeof(hdr));
7345 		strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
7346 		hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
7347 		if(m_header.GetHeaderHandle(&hdr) == false)
7348 		{
7349 			IPACMERR("Failed to get QMAP header.\n");
7350 			res = IPACM_FAILURE;
7351 			goto fail;
7352 		}
7353 		rt_rule_entry->rule.hdr_hdl = hdr.hdl;
7354 		rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS;
7355 		/*  default v4 rt-rule */
7356 #ifdef IPA_RT_SUPPORT_COAL
7357 			rt_rule_entry->rule.coalesce = false;
7358 #endif
7359 		/* default v4 rt-rule */
7360 		if (false == m_routing.AddRoutingRule(rt_rule))
7361 		{
7362 			IPACMERR("Routing rule addition failed!\n");
7363 			res = IPACM_FAILURE;
7364 			goto fail;
7365 		}
7366 		else if (rt_rule_entry->status)
7367 		{
7368 			IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
7369 			res = rt_rule_entry->status;
7370 			goto fail;
7371 		}
7372 		dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
7373 		IPACMDBG_H("ipv4 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[0]);
7374 
7375 		/* RSC TCP rule*/
7376 		rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
7377 		rt_rule_entry->rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP;
7378 #ifdef IPA_RT_SUPPORT_COAL
7379 		if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable)
7380 			rt_rule_entry->rule.coalesce = true;
7381 		else
7382 			rt_rule_entry->rule.coalesce = false;
7383 #endif
7384 		if (false == m_routing.AddRoutingRule(rt_rule))
7385 		{
7386 			IPACMERR("Routing rule addition failed!\n");
7387 			res = IPACM_FAILURE;
7388 			goto fail;
7389 		}
7390 		else if (rt_rule_entry->status)
7391 		{
7392 			IPACMERR("rsc tcp rt rule adding failed. Result=%d\n", rt_rule_entry->status);
7393 			res = rt_rule_entry->status;
7394 			goto fail;
7395 		}
7396 		dft_coalesce_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
7397 		IPACMDBG_H("ipv4 wan iface rsc tcp rt-rule hdll=0x%x\n enable(%d)", dft_coalesce_rt_rule_hdl[0],
7398 			IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable);
7399 
7400 		/* RSB UDP rule*/
7401 		rt_rule_entry->rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_UDP;
7402 #ifdef IPA_RT_SUPPORT_COAL
7403 		if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable)
7404 			rt_rule_entry->rule.coalesce = true;
7405 		else
7406 			rt_rule_entry->rule.coalesce = false;
7407 #endif
7408 		if (false == m_routing.AddRoutingRule(rt_rule))
7409 		{
7410 			IPACMERR("Routing rule addition failed!\n");
7411 			res = IPACM_FAILURE;
7412 			goto fail;
7413 		}
7414 		else if (rt_rule_entry->status)
7415 		{
7416 			IPACMERR("rsb udp rt rule adding failed. Result=%d\n", rt_rule_entry->status);
7417 			res = rt_rule_entry->status;
7418 			goto fail;
7419 		}
7420 		dft_coalesce_rt_rule_hdl[1] = rt_rule_entry->rt_rule_hdl;
7421 		IPACMDBG_H("ipv4 wan iface rsb udp rt-rule hdll=0x%x enable(%d)\n", dft_coalesce_rt_rule_hdl[1],
7422 			IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable);
7423 fail:
7424 	free(rt_rule);
7425 	}
7426 	/* v6 */
7427 	if (num_dft_rt_v6 !=0)
7428 	{
7429 		for (i = 0; i < 2*num_dft_rt_v6; i++)
7430 		{
7431 			/* delete v6 colasce rules */
7432 			if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
7433 			{
7434 				IPACMERR("Colasce Routing rule deletion failed!\n");
7435 				return  IPACM_FAILURE;
7436 			}
7437 			/* delete v6 default rules */
7438 			if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false)
7439 			{
7440 				IPACMERR("Routing rule deletion failed!\n");
7441 				return  IPACM_FAILURE;
7442 			}
7443 		}
7444 
7445 		rt_rule = (struct ipa_ioc_add_rt_rule *)
7446 			calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
7447 				NUM_RULES * sizeof(struct ipa_rt_rule_add));
7448 		if (!rt_rule)
7449 		{
7450 			IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n");
7451 			return IPACM_FAILURE;
7452 		}
7453 		rt_rule->commit = 1;
7454 		rt_rule->num_rules = NUM_RULES;
7455 		rt_rule->ip = IPA_IP_v6;
7456 
7457 		for (i = 0; i < num_dft_rt_v6; i++)
7458 		{
7459 			/* setup same rule for v6_wan table */
7460 			strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name));
7461 			rt_rule_entry = &rt_rule->rules[0];
7462 			rt_rule_entry->at_rear = false;
7463 			rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
7464 			rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = ipv6_addr[i][0];
7465 			rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = ipv6_addr[i][1];
7466 			rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = ipv6_addr[i][2];
7467 			rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = ipv6_addr[i][3];
7468 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
7469 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
7470 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
7471 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
7472 			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
7473 				rt_rule_entry->rule.hashable = false;
7474 			strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
7475 			hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
7476 			if(m_header.GetHeaderHandle(&hdr) == false)
7477 			{
7478 				IPACMERR("Failed to get QMAP header.\n");
7479 				return IPACM_FAILURE;
7480 			}
7481 			rt_rule_entry->rule.hdr_hdl = hdr.hdl;
7482 			rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS;
7483 			/* legacy default v4 rt-rule */
7484 #ifdef IPA_RT_SUPPORT_COAL
7485 			rt_rule_entry->rule.coalesce = false;
7486 #endif
7487 			/* legacy default v6 rt-rule */
7488 			if (false == m_routing.AddRoutingRule(rt_rule))
7489 			{
7490 				IPACMERR("Routing rule addition failed!\n");
7491 				res = IPACM_FAILURE;
7492 				goto fail2;
7493 			}
7494 			else if (rt_rule_entry->status)
7495 			{
7496 				IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
7497 				res = rt_rule_entry->status;
7498 				goto fail2;
7499 			}
7500 			dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*i] = rt_rule_entry->rt_rule_hdl;
7501 
7502 			/* setup same rule for v6_lan table*/
7503 			strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name));
7504 			if (false == m_routing.AddRoutingRule(rt_rule))
7505 			{
7506 				IPACMERR("Routing rule addition failed!\n");
7507 				res = IPACM_FAILURE;
7508 				goto fail2;
7509 			}
7510 			else if (rt_rule_entry->status)
7511 			{
7512 				IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
7513 				res = rt_rule_entry->status;
7514 				goto fail2;
7515 			}
7516 			dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*i+1] = rt_rule_entry->rt_rule_hdl;
7517 			IPACMDBG_H("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, entry: %d %d\n",
7518 				dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*i],
7519 				dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*i+1],
7520 				MAX_DEFAULT_v4_ROUTE_RULES + 2*i,
7521 				MAX_DEFAULT_v4_ROUTE_RULES + 2*i+1);
7522 			/* RSC TCP rule*/
7523 			rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
7524 			rt_rule_entry->rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP;
7525 #ifdef IPA_RT_SUPPORT_COAL
7526 			if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable)
7527 				rt_rule_entry->rule.coalesce = true;
7528 			else
7529 				rt_rule_entry->rule.coalesce = false;
7530 #endif
7531 			if (false == m_routing.AddRoutingRule(rt_rule))
7532 			{
7533 				IPACMERR("Routing rule addition failed!\n");
7534 				res = IPACM_FAILURE;
7535 				goto fail2;
7536 			}
7537 			else if (rt_rule_entry->status)
7538 			{
7539 				IPACMERR("rsc tcp rt rule adding failed. Result=%d\n", rt_rule_entry->status);
7540 				res = rt_rule_entry->status;
7541 				goto fail2;
7542 			}
7543 			dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*i] = rt_rule_entry->rt_rule_hdl;
7544 			IPACMDBG_H("ipv6 wan iface rsc tcp rt-rule hdll=0x%x\n enable(%d)", dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*i],
7545 				IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable);
7546 			/* RSB UDP rule*/
7547 			rt_rule_entry->rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_UDP;
7548 #ifdef IPA_RT_SUPPORT_COAL
7549 			if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable)
7550 				rt_rule_entry->rule.coalesce = true;
7551 			else
7552 				rt_rule_entry->rule.coalesce = false;
7553 #endif
7554 			if (false == m_routing.AddRoutingRule(rt_rule))
7555 			{
7556 				IPACMERR("Routing rule addition failed!\n");
7557 				res = IPACM_FAILURE;
7558 				goto fail2;
7559 			}
7560 			else if (rt_rule_entry->status)
7561 			{
7562 				IPACMERR("rsb udp rt rule adding failed. Result=%d\n", rt_rule_entry->status);
7563 				res = rt_rule_entry->status;
7564 				goto fail2;
7565 			}
7566 			dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*i+1] = rt_rule_entry->rt_rule_hdl;
7567 			IPACMDBG_H("ipv6 wan iface rsb udp rt-rule hdll=0x%x\n enable(%d)", dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*i+1],
7568 				IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable);
7569 		}
7570 fail2:
7571 	free(rt_rule);
7572 	}
7573 	return res;
7574 }
7575 
add_offload_frag_rule()7576 int IPACM_Wan::add_offload_frag_rule()
7577 {
7578 	int fd;
7579 	int len, res = IPACM_SUCCESS;
7580 	uint8_t mux_id;
7581 	ipa_ioc_add_flt_rule *pFilteringTable = NULL;
7582 
7583 	mux_id = ext_prop->ext[0].mux_id;
7584 	/* contruct filter rules to pcie modem */
7585 	struct ipa_flt_rule_add flt_rule_entry;
7586 	ipa_ioc_generate_flt_eq flt_eq;
7587 
7588 	/* construct rule */
7589 	IPACMDBG_H("adding MHi frag rule\n");
7590 	len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add);
7591 	pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len);
7592 	if (pFilteringTable == NULL)
7593 	{
7594 		IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
7595 		return IPACM_FAILURE;
7596 	}
7597 	memset(pFilteringTable, 0, len);
7598 
7599 	pFilteringTable->commit = 1;
7600 	pFilteringTable->global = false;
7601 	pFilteringTable->ip = IPA_IP_v4;
7602 	pFilteringTable->num_rules = (uint8_t)1;
7603 
7604 	/* Configuring Fragment Filtering Rule */
7605 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
7606 	flt_rule_entry.at_rear = false;
7607 	flt_rule_entry.flt_rule_hdl = -1;
7608 	flt_rule_entry.status = -1;
7609 
7610 	flt_rule_entry.rule.retain_hdr = 1;
7611 	flt_rule_entry.rule.to_uc = 0;
7612 	flt_rule_entry.rule.eq_attrib_type = 1;
7613 	flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
7614 	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
7615 		flt_rule_entry.rule.hashable = true;
7616 	IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
7617 	memcpy(&flt_rule_entry.rule.attrib,
7618 				&rx_prop->rx[0].attrib,
7619 				sizeof(flt_rule_entry.rule.attrib));
7620 
7621 	flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
7622 
7623 	/* generate eq */
7624 	memset(&flt_eq, 0, sizeof(flt_eq));
7625 	memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
7626 	flt_eq.ip = IPA_IP_v4;
7627 
7628 	fd = open(IPA_DEVICE_NAME, O_RDWR);
7629 	if (fd < 0)
7630 	{
7631 		IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
7632 		free(pFilteringTable);
7633 		return IPACM_FAILURE;
7634 	}
7635 
7636 	if(0 != ioctl(fd, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) //define and cpy attribute to this struct
7637 	{
7638 		IPACMERR("Failed to get eq_attrib\n");
7639 		goto fail;
7640 	}
7641 	memcpy(&flt_rule_entry.rule.eq_attrib,
7642 		&flt_eq.eq_attrib,
7643 		sizeof(flt_rule_entry.rule.eq_attrib));
7644 	memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
7645 
7646 	/* add rule */
7647 	if(false == m_filtering.AddOffloadFilteringRule(pFilteringTable, mux_id, 1))
7648 	{
7649 		IPACMERR("Failed to install WAN DL filtering table.\n");
7650 		res = IPACM_FAILURE;
7651 		goto fail;
7652 	}
7653 
7654 	/* save handle */
7655 	mhi_dl_v4_frag_hdl = pFilteringTable->rules[0].flt_rule_hdl;
7656 
7657 fail:
7658 	close(fd);
7659 	if(pFilteringTable != NULL)
7660 	{
7661 		free(pFilteringTable);
7662 	}
7663 	return res;
7664 }
7665 
delete_offload_frag_rule()7666 int IPACM_Wan::delete_offload_frag_rule()
7667 {
7668 	int res = IPACM_SUCCESS;
7669 	int len;
7670 	ipa_ioc_del_flt_rule *pFilteringTable = NULL;
7671 
7672 	struct ipa_flt_rule_del flt_rule_entry;
7673 
7674 	IPACMDBG_H("deleting MHI frag rule \n");
7675 	len = sizeof(struct ipa_ioc_del_flt_rule) + sizeof(struct ipa_flt_rule_del);
7676 	pFilteringTable = (struct ipa_ioc_del_flt_rule*)malloc(len);
7677 	if (pFilteringTable == NULL)
7678 	{
7679 		IPACMERR("Error Locate ipa_ioc_del_flt_rule memory...\n");
7680 		return false;
7681 	}
7682 	memset(pFilteringTable, 0, len);
7683 
7684 	pFilteringTable->commit = 1;
7685 	pFilteringTable->ip = IPA_IP_v4;
7686 	pFilteringTable->num_hdls = (uint8_t)1;
7687 
7688 	if (mhi_dl_v4_frag_hdl == 0)
7689 	{
7690 		IPACMERR("invalid dl_v4_frag_hdl.\n");
7691 		res = false;
7692 		goto fail;
7693 	}
7694 
7695 	/* Configuring Software-Routing Filtering Rule */
7696 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_del));
7697 	flt_rule_entry.hdl = mhi_dl_v4_frag_hdl;
7698 
7699 	memcpy(&(pFilteringTable->hdl[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del));
7700 
7701 	if(false == m_filtering.DelOffloadFilteringRule(pFilteringTable))
7702 	{
7703 		IPACMERR("Failed to delete DL offload frag rule.\n");
7704 		res = false;
7705 		goto fail;
7706 	}
7707 	mhi_dl_v4_frag_hdl = 0;
7708 
7709 fail:
7710 	if(pFilteringTable != NULL)
7711 	{
7712 		free(pFilteringTable);
7713 	}
7714 	return res;
7715 }
7716 
add_icmpv6_exception_rule()7717 int IPACM_Wan::add_icmpv6_exception_rule()
7718 {
7719 	int fd;
7720 	int len, res = IPACM_SUCCESS;
7721 	uint8_t mux_id;
7722 	ipa_ioc_add_flt_rule *pFilteringTable = NULL;
7723 
7724 	mux_id = ext_prop->ext[0].mux_id;
7725 	/* contruct filter rules to pcie modem */
7726 	struct ipa_flt_rule_add flt_rule_entry;
7727 	ipa_ioc_generate_flt_eq flt_eq;
7728 
7729 	/* construct rule */
7730 	IPACMDBG_H("adding MHI icmpv6 rule\n");
7731 	len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add);
7732 	pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len);
7733 	if (pFilteringTable == NULL)
7734 	{
7735 		IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
7736 		return IPACM_FAILURE;
7737 	}
7738 	memset(pFilteringTable, 0, len);
7739 
7740 	pFilteringTable->commit = 1;
7741 	pFilteringTable->global = false;
7742 	pFilteringTable->ip = IPA_IP_v6;
7743 	pFilteringTable->num_rules = (uint8_t)1;
7744 
7745 	/* Configuring ICMPv6 Filtering Rule */
7746 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
7747 	flt_rule_entry.rule.retain_hdr = 1;
7748 	flt_rule_entry.rule.to_uc = 0;
7749 	flt_rule_entry.rule.eq_attrib_type = 0;
7750 	flt_rule_entry.at_rear = false;
7751 	flt_rule_entry.flt_rule_hdl = -1;
7752 	flt_rule_entry.status = -1;
7753 	flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
7754 	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
7755 		flt_rule_entry.rule.hashable = true;
7756 	IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
7757 	memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
7758 	flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
7759 	flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6;
7760 
7761 	/* generate eq */
7762 	memset(&flt_eq, 0, sizeof(flt_eq));
7763 	memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
7764 	flt_eq.ip = IPA_IP_v6;
7765 
7766 	fd = open(IPA_DEVICE_NAME, O_RDWR);
7767 	if (fd < 0)
7768 	{
7769 		IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
7770 		free(pFilteringTable);
7771 		return IPACM_FAILURE;
7772 	}
7773 
7774 	if(0 != ioctl(fd, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) //define and cpy attribute to this struct
7775 	{
7776 		IPACMERR("Failed to get eq_attrib\n");
7777 		res = IPACM_FAILURE;
7778 		goto fail;
7779 	}
7780 	memcpy(&flt_rule_entry.rule.eq_attrib,
7781 		&flt_eq.eq_attrib,
7782 		sizeof(flt_rule_entry.rule.eq_attrib));
7783 	memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
7784 
7785 	/* add rule */
7786 	if(false == m_filtering.AddOffloadFilteringRule(pFilteringTable, mux_id, 1))
7787 	{
7788 		IPACMERR("Failed to install WAN DL filtering table.\n");
7789 		res = IPACM_FAILURE;
7790 		goto fail;
7791 	}
7792 
7793 	/* save handle */
7794 	icmpv6_exception_hdl = pFilteringTable->rules[0].flt_rule_hdl;
7795 
7796 fail:
7797 	close(fd);
7798 	if(pFilteringTable != NULL)
7799 	{
7800 		free(pFilteringTable);
7801 	}
7802 	return res;
7803 }
7804 
delete_icmpv6_exception_rule()7805 int IPACM_Wan::delete_icmpv6_exception_rule()
7806 {
7807 	int len, res = IPACM_SUCCESS;
7808 	ipa_ioc_del_flt_rule *pFilteringTable = NULL;
7809 
7810 	struct ipa_flt_rule_del flt_rule_entry;
7811 
7812 	IPACMDBG_H("deleting MHI icmpv6 rule \n");
7813 	len = sizeof(struct ipa_ioc_del_flt_rule) + sizeof(struct ipa_flt_rule_del);
7814 	pFilteringTable = (struct ipa_ioc_del_flt_rule*)malloc(len);
7815 	if (pFilteringTable == NULL)
7816 	{
7817 		IPACMERR("Error Locate ipa_ioc_del_flt_rule memory...\n");
7818 		return IPACM_FAILURE;
7819 	}
7820 	memset(pFilteringTable, 0, len);
7821 
7822 	pFilteringTable->commit = 1;
7823 	pFilteringTable->ip = IPA_IP_v6;
7824 	pFilteringTable->num_hdls = (uint8_t)1;
7825 
7826 	if (icmpv6_exception_hdl == 0)
7827 	{
7828 		IPACMERR("invalid icmpv6_exception_hdl.\n");
7829 		res = IPACM_FAILURE;
7830 		goto fail;
7831 	}
7832 
7833 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_del));
7834 	flt_rule_entry.hdl = icmpv6_exception_hdl;
7835 
7836 	memcpy(&(pFilteringTable->hdl[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del));
7837 
7838 	if(false == m_filtering.DelOffloadFilteringRule(pFilteringTable))
7839 	{
7840 		IPACMERR("Failed to delete MHI icmpv6 rule.\n");
7841 		res = IPACM_FAILURE;
7842 		goto fail;
7843 	}
7844 	icmpv6_exception_hdl = 0;
7845 
7846 fail:
7847 	if(pFilteringTable != NULL)
7848 	{
7849 		free(pFilteringTable);
7850 	}
7851 	return res;
7852 }
7853 
add_tcp_fin_rst_exception_rule()7854 int IPACM_Wan::add_tcp_fin_rst_exception_rule()
7855 {
7856 	int fd;
7857 	int len, res = IPACM_SUCCESS;
7858 	uint8_t mux_id;
7859 	ipa_ioc_add_flt_rule *pFilteringTable = NULL;
7860 
7861 	mux_id = ext_prop->ext[0].mux_id;
7862 	/* contruct filter rules to pcie modem */
7863 	struct ipa_flt_rule_add flt_rule_entry;
7864 	ipa_ioc_generate_flt_eq flt_eq;
7865 
7866 	/* construct rule */
7867 	IPACMDBG_H("adding MHI TCP FIN RST rule\n");
7868 	len = sizeof(struct ipa_ioc_add_flt_rule) + (2 * sizeof(struct ipa_flt_rule_add));
7869 	pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len);
7870 	if (pFilteringTable == NULL)
7871 	{
7872 		IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
7873 		return IPACM_FAILURE;
7874 	}
7875 	memset(pFilteringTable, 0, len);
7876 
7877 	pFilteringTable->commit = 1;
7878 	pFilteringTable->global = false;
7879 	pFilteringTable->ip = IPA_IP_v4;
7880 	pFilteringTable->num_rules = (uint8_t)2;
7881 
7882 	/* Configuring TCP FIN RST Filtering Rule */
7883 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
7884 	flt_rule_entry.rule.retain_hdr = 1;
7885 	flt_rule_entry.rule.to_uc = 0;
7886 	flt_rule_entry.rule.eq_attrib_type = 0;
7887 	flt_rule_entry.at_rear = false;
7888 	flt_rule_entry.flt_rule_hdl = -1;
7889 	flt_rule_entry.status = -1;
7890 	flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
7891 	/*
7892 	 * need this since fin is last packet in an ongoing TCP connection
7893 	 * so it will always match the previous hash and take MHIP path
7894 	 */
7895 	flt_rule_entry.rule.hashable = false;
7896 
7897 	IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
7898 	memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
7899 	flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
7900 	flt_rule_entry.rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP;
7901 
7902 	/* generate eq */
7903 	memset(&flt_eq, 0, sizeof(flt_eq));
7904 	memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
7905 	flt_eq.ip = IPA_IP_v4;
7906 
7907 	fd = open(IPA_DEVICE_NAME, O_RDWR);
7908 	if (fd < 0)
7909 	{
7910 		IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
7911 		free(pFilteringTable);
7912 		return IPACM_FAILURE;
7913 	}
7914 
7915 	if(0 != ioctl(fd, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) //define and cpy attribute to this struct
7916 	{
7917 		IPACMERR("Failed to get eq_attrib\n");
7918 		res = IPACM_FAILURE;
7919 		goto fail;
7920 	}
7921 	memcpy(&flt_rule_entry.rule.eq_attrib,
7922 		&flt_eq.eq_attrib,
7923 		sizeof(flt_rule_entry.rule.eq_attrib));
7924 
7925 	/* set the bit mask to use MEQ32_IHL offset */
7926 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
7927 			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7);
7928 		else
7929 			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8);
7930 
7931 	/* add offset to compare TCP flags */
7932 	flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1;
7933 	flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12;
7934 
7935 	/* add TCP FIN RULE */
7936 	flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_FIN_SHIFT);
7937 	flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_FIN_SHIFT);
7938 	memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
7939 
7940 	/* add TCP RST rule*/
7941 	flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_RST_SHIFT);
7942 	flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_RST_SHIFT);
7943 	memcpy(&(pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
7944 
7945 	/* add rules */
7946 	if(false == m_filtering.AddOffloadFilteringRule(pFilteringTable, mux_id, 1))
7947 	{
7948 		IPACMERR("Failed to install WAN DL filtering table.\n");
7949 		res = IPACM_FAILURE;
7950 		goto fail;
7951 	}
7952 
7953 	/* save handle */
7954 	tcp_fin_hdl = pFilteringTable->rules[0].flt_rule_hdl;
7955 	tcp_rst_hdl = pFilteringTable->rules[1].flt_rule_hdl;
7956 
7957 fail:
7958 	close(fd);
7959 	if(pFilteringTable != NULL)
7960 	{
7961 		free(pFilteringTable);
7962 	}
7963 	return res;
7964 }
7965 
delete_tcp_fin_rst_exception_rule()7966 int IPACM_Wan::delete_tcp_fin_rst_exception_rule()
7967 {
7968 	int len, res = IPACM_SUCCESS;
7969 	ipa_ioc_del_flt_rule *pFilteringTable = NULL;
7970 
7971 	struct ipa_flt_rule_del flt_rule_entry;
7972 
7973 	IPACMDBG_H("deleting MHI TCP FIN RST rule \n");
7974 	len = sizeof(struct ipa_ioc_del_flt_rule) + (2 * sizeof(struct ipa_flt_rule_del));
7975 	pFilteringTable = (struct ipa_ioc_del_flt_rule*)malloc(len);
7976 	if (pFilteringTable == NULL)
7977 	{
7978 		IPACMERR("Error Locate ipa_ioc_del_flt_rule memory...\n");
7979 		return IPACM_FAILURE;
7980 	}
7981 	memset(pFilteringTable, 0, len);
7982 
7983 	pFilteringTable->commit = 1;
7984 	pFilteringTable->ip = IPA_IP_v4;
7985 	pFilteringTable->num_hdls = (uint8_t)2;
7986 
7987 	if (tcp_fin_hdl == 0 || tcp_rst_hdl == 0)
7988 	{
7989 		IPACMERR("invalid tcp_fin_rst_hdl.\n");
7990 		res = IPACM_FAILURE;
7991 		goto fail;
7992 	}
7993 
7994 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_del));
7995 	flt_rule_entry.hdl = tcp_fin_hdl;
7996 
7997 	memcpy(&(pFilteringTable->hdl[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del));
7998 
7999 	flt_rule_entry.hdl = tcp_rst_hdl;
8000 
8001 	memcpy(&(pFilteringTable->hdl[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del));
8002 
8003 	if(false == m_filtering.DelOffloadFilteringRule(pFilteringTable))
8004 	{
8005 		IPACMERR("Failed to delete MHI TCP FIN RST rule.\n");
8006 		res = IPACM_FAILURE;
8007 		goto fail;
8008 	}
8009 	tcp_fin_hdl = 0;
8010 	tcp_rst_hdl = 0;
8011 
8012 fail:
8013 	if(pFilteringTable != NULL)
8014 	{
8015 		free(pFilteringTable);
8016 	}
8017 	return res;
8018 }
8019 
query_mtu_size()8020 int IPACM_Wan::query_mtu_size()
8021 {
8022 	int fd;
8023 	struct ifreq if_mtu;
8024 
8025 	fd = socket(AF_INET, SOCK_DGRAM, 0);
8026 	if ( fd < 0 ) {
8027 		IPACMERR("ipacm: socket open failed [%d]\n", fd);
8028 		return IPACM_FAILURE;
8029 	}
8030 
8031 	strlcpy(if_mtu.ifr_name, dev_name, IFNAMSIZ);
8032 	IPACMDBG_H("device name: %s\n", dev_name);
8033 	if_mtu.ifr_name[IFNAMSIZ - 1] = '\0';
8034 
8035 	if ( ioctl(fd, SIOCGIFMTU, &if_mtu) < 0 ) {
8036 		IPACMERR("ioctl failed to get mtu\n");
8037 		close(fd);
8038 		return IPACM_FAILURE;
8039 	}
8040 	IPACMDBG_H("mtu=[%d]\n", if_mtu.ifr_mtu);
8041 	if (if_mtu.ifr_mtu <= DEFAULT_MTU_SIZE) {
8042 		mtu_v4 = mtu_v6 = if_mtu.ifr_mtu;
8043 	}else {
8044 		mtu_v4 = mtu_v6 = DEFAULT_MTU_SIZE;
8045 	}
8046 	IPACMDBG_H("Updated mtu=[%d] for (%s)\n", mtu_v4, dev_name);
8047 
8048 	close(fd);
8049 	return IPACM_SUCCESS;
8050 }
8051 
8052 /* construct complete ethernet header */
handle_gw_mac_renew(ipacm_event_data_all * data,int index_client)8053 int IPACM_Wan::handle_gw_mac_renew(ipacm_event_data_all *data, int index_client)
8054 {
8055 	int index = IPACM_INVALID_INDEX;
8056 
8057 	/* checking if client has same ipv4, v6 will put future work */
8058 	if (data->iptype == IPA_IP_v4)
8059 	{
8060 		index = get_wan_client_index_ipv4(data->ipv4_addr);
8061 		if (index != IPACM_INVALID_INDEX)
8062 		{
8063 			IPACMDBG_H("Matched client index: %d\n", index);
8064 			IPACMDBG_H("Client MAC in cache %02x:%02x:%02x:%02x:%02x:%02x\n",
8065 				get_client_memptr(wan_client, index)->mac[0],
8066 				get_client_memptr(wan_client, index)->mac[1],
8067 				get_client_memptr(wan_client, index)->mac[2],
8068 				get_client_memptr(wan_client, index)->mac[3],
8069 					get_client_memptr(wan_client, index)->mac[4],
8070 					get_client_memptr(wan_client, index)->mac[5]);
8071 
8072 			/* check mac same or not */
8073 			if ((data->mac_addr[0] == get_client_memptr(wan_client, index)->mac[0]) &&
8074 				(data->mac_addr[1] == get_client_memptr(wan_client, index)->mac[1]) &&
8075 				(data->mac_addr[2] == get_client_memptr(wan_client, index)->mac[2]) &&
8076 				(data->mac_addr[3] == get_client_memptr(wan_client, index)->mac[3]) &&
8077 				(data->mac_addr[4] == get_client_memptr(wan_client, index)->mac[4]) &&
8078 				(data->mac_addr[5] == get_client_memptr(wan_client, index)->mac[5]))
8079 			{
8080 				IPACMDBG_H(" No need client (%d) mac renew with IPv4 (0x%x)\n", index, data->ipv4_addr);
8081 				return IPACM_FAILURE;
8082 			}
8083 			else
8084 			{
8085 				IPACMDBG_H(" client %d need mac renew with IPv4 (0x%x)\n", index, data->ipv4_addr);
8086 
8087 				/* Del NAT rules before ipv4 RT rules are delete */
8088 				if(get_client_memptr(wan_client, index)->ipv4_set == true)
8089 				{
8090 					IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wan_client, index)->v4_addr);
8091 					CtList->HandleSTAClientDelEvt(get_client_memptr(wan_client, index)->v4_addr);
8092 				}
8093 
8094 				/* clean up STA header / routing rule */
8095 				if (data->ipv4_addr == wan_v4_addr_gw && active_v4)
8096 				{
8097 					handle_route_del_evt(IPA_IP_v4, true);
8098 					IPACMDBG_H("Delete default v4 routing rules\n");
8099 					hdr_hdl_sta_v4 = 0;
8100 					header_set_v4 = false;
8101 					header_partial_default_wan_v4 = true;
8102 
8103 					if (active_v6)
8104 					{
8105 						handle_route_del_evt(IPA_IP_v6, true);
8106 						IPACMDBG_H("Delete default v6 routing rules\n");
8107 						header_partial_default_wan_v6 = true;
8108 					}
8109 					hdr_hdl_sta_v6 = 0;
8110 					header_set_v6 = false;
8111 				}
8112 
8113 				/* clean up client header routing rule entry */
8114 				if(delete_wan_rtrules(index, IPA_IP_v4))
8115 				{
8116 						IPACMERR("unbale to delete wan-client v4 route rules for index %d\n", index);
8117 						return IPACM_FAILURE;
8118 				}
8119 
8120 				get_client_memptr(wan_client, index)->route_rule_set_v4 = false;
8121 				get_client_memptr(wan_client, index)->ipv4_set = false;
8122 
8123 				IPACMDBG_H("Delete client %d header\n", index);
8124 				if(get_client_memptr(wan_client, index)->ipv4_header_set == true)
8125 				{
8126 					if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, index)->hdr_hdl_v4) == false)
8127 					{
8128 						IPACMERR("unable to delete client v4 header for index %d\n", index);
8129 						return IPACM_FAILURE;
8130 					}
8131 					get_client_memptr(wan_client, index)->ipv4_header_set = false;
8132 				}
8133 
8134 				if(delete_wan_rtrules(index, IPA_IP_v6))
8135 				{
8136 					IPACMERR("unbale to delete wan-client v6 route rules for index %d\n", index);
8137 					return IPACM_FAILURE;
8138 				}
8139 				get_client_memptr(wan_client, index)->route_rule_set_v6 = 0;
8140 				get_client_memptr(wan_client, index)->ipv6_set = 0;
8141 				if(get_client_memptr(wan_client, index)->ipv6_header_set == true)
8142 				{
8143 					if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, index)->hdr_hdl_v6) == false)
8144 					{
8145 						IPACMERR("unable to delete client v6 header for index %d\n", index);
8146 						return IPACM_FAILURE;
8147 					}
8148 					get_client_memptr(wan_client, index)->ipv6_header_set = false;
8149 				}
8150 				/* replacing the old mac to new_mac on same entry */
8151 				get_client_memptr(wan_client, index)->mac[0] = data->mac_addr[0];
8152 				get_client_memptr(wan_client, index)->mac[1] = data->mac_addr[1];
8153 				get_client_memptr(wan_client, index)->mac[2] = data->mac_addr[2];
8154 				get_client_memptr(wan_client, index)->mac[3] = data->mac_addr[3];
8155 				get_client_memptr(wan_client, index)->mac[4] = data->mac_addr[4];
8156 				get_client_memptr(wan_client, index)->mac[5] = data->mac_addr[5];
8157 				index_client = index;
8158 				return IPACM_SUCCESS;
8159 			}
8160 		}
8161 	}
8162 	return IPACM_FAILURE;
8163 }
8164