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