1 /*
2 Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7 * Redistributions of source code must retain the above copyright
8   notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10   copyright notice, this list of conditions and the following
11   disclaimer in the documentation and/or other materials provided
12   with the distribution.
13 * Neither the name of The Linux Foundation nor the names of its
14   contributors may be used to endorse or promote products derived
15   from this software without specific prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.Z
28 */
29 /*!
30   @file
31   IPACM_Iface.cpp
32 
33   @brief
34   This file implements the basis Iface functionality.
35 
36   @Author
37   Skylar Chang
38 
39 */
40 #include <fcntl.h>
41 #include <sys/ioctl.h>
42 #include <IPACM_Netlink.h>
43 #include <IPACM_Iface.h>
44 #include <IPACM_Lan.h>
45 #include <IPACM_Wan.h>
46 #include <IPACM_Wlan.h>
47 #include <string.h>
48 
49 extern "C"
50 {
51 #include <ifaddrs.h>
52 }
53 
54 
55 const char *IPACM_Iface::DEVICE_NAME = "/dev/ipa";
56 IPACM_Routing IPACM_Iface::m_routing;
57 IPACM_Filtering IPACM_Iface::m_filtering;
58 IPACM_Header IPACM_Iface::m_header;
59 
60 IPACM_Config *IPACM_Iface::ipacmcfg = IPACM_Config::GetInstance();
61 
IPACM_Iface(int iface_index)62 IPACM_Iface::IPACM_Iface(int iface_index)
63 {
64 	ip_type = IPACM_IP_NULL; /* initially set invalid */
65 	num_dft_rt_v6 = 0;
66 	softwarerouting_act = false;
67 	ipa_if_num = iface_index;
68 	ipa_if_cate = IPACM_Iface::ipacmcfg->iface_table[iface_index].if_cat;
69 
70 	iface_query = NULL;
71 	tx_prop = NULL;
72 	rx_prop = NULL;
73 
74 	memcpy(dev_name,
75 				 IPACM_Iface::ipacmcfg->iface_table[iface_index].iface_name,
76 				 sizeof(IPACM_Iface::ipacmcfg->iface_table[iface_index].iface_name));
77 
78 	memset(dft_v4fl_rule_hdl, 0, sizeof(dft_v4fl_rule_hdl));
79 	memset(dft_v6fl_rule_hdl, 0, sizeof(dft_v6fl_rule_hdl));
80 
81 	memset(dft_rt_rule_hdl, 0, sizeof(dft_rt_rule_hdl));
82 	memset(software_routing_fl_rule_hdl, 0, sizeof(software_routing_fl_rule_hdl));
83 	memset(ipv6_addr, 0, sizeof(ipv6_addr));
84 
85 	query_iface_property();
86 	IPACMDBG_H(" create iface-index(%d) constructor\n", ipa_if_num);
87 	return;
88 }
89 
90 /* software routing enable */
handle_software_routing_enable(bool mhip)91 int IPACM_Iface::handle_software_routing_enable(bool mhip)
92 {
93 	int fd =0;
94 	int res = IPACM_SUCCESS;
95 	struct ipa_flt_rule_add flt_rule_entry;
96 	ipa_ioc_add_flt_rule *m_pFilteringTable;
97 	/* contruct filter rules to pcie modem */
98 	ipa_ioc_generate_flt_eq flt_eq;
99 
100 	IPACMDBG("\n");
101 	if (softwarerouting_act == true)
102 	{
103 		IPACMDBG("already setup software_routing rule for (%s)iface ip-family %d\n",
104 						     IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ip_type);
105 		return IPACM_SUCCESS;
106 	}
107 
108 	if(rx_prop == NULL)
109 	{
110 		IPACMDBG("No rx properties registered for iface %s\n", dev_name);
111 		return IPACM_SUCCESS;
112 	}
113 
114 	m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)
115 		 calloc(1,
116 						sizeof(struct ipa_ioc_add_flt_rule) +
117 						1 * sizeof(struct ipa_flt_rule_add)
118 						);
119 	if (!m_pFilteringTable)
120 	{
121 		IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
122 		return IPACM_FAILURE;
123 	}
124 
125 	m_pFilteringTable->commit = 1;
126 	m_pFilteringTable->global = false;
127 	m_pFilteringTable->num_rules = (uint8_t)1;
128 
129 	/* Configuring Software-Routing Filtering Rule */
130 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
131 
132 	flt_rule_entry.at_rear = false;
133 	flt_rule_entry.flt_rule_hdl = -1;
134 	flt_rule_entry.status = -1;
135 	flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
136 	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
137 		flt_rule_entry.rule.hashable = true;
138 	memcpy(&flt_rule_entry.rule.attrib,
139 				 &rx_prop->rx[0].attrib,
140 				 sizeof(flt_rule_entry.rule.attrib));
141 
142 	memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
143 
144 	/* check iface is v4 or v6 or both*/
145 
146 		/* handle v4 */
147 		m_pFilteringTable->ip = IPA_IP_v4;
148 
149 	fd = open(IPA_DEVICE_NAME, O_RDWR);
150 	if (fd < 0)
151 	{
152 		IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
153 		free(m_pFilteringTable);
154 		return IPACM_FAILURE;
155 	}
156 
157 	if (mhip)
158 	{
159 		/* generate eq */
160 		memset(&flt_eq, 0, sizeof(flt_eq));
161 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
162 		flt_eq.ip = IPA_IP_v4;
163 
164 
165 		if(0 != ioctl(fd, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) //define and cpy attribute to this struct
166 		{
167 			IPACMERR("Failed to get eq_attrib\n");
168 			res = IPACM_FAILURE;
169 			goto fail;
170 		}
171 		memcpy(&flt_rule_entry.rule.eq_attrib,
172 			&flt_eq.eq_attrib,
173 			sizeof(flt_rule_entry.rule.eq_attrib));
174 		memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
175 
176 		/* add rule */
177 		if(false == m_filtering.AddOffloadFilteringRule(m_pFilteringTable, IPACM_Iface::ipacmcfg->GetQmapId(), 1))
178 		{
179 			IPACMERR("Failed to install WAN DL filtering table.\n");
180 			res = IPACM_FAILURE;
181 			goto fail;
182 		}
183 	}
184 	else
185 	{
186 		m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
187 		if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
188 		{
189 			IPACMERR("Error Adding Filtering rule, aborting...\n");
190 			res = IPACM_FAILURE;
191 			goto fail;
192 		}
193 		else if (m_pFilteringTable->rules[0].status)
194 		{
195 			IPACMERR("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status);
196 			res = IPACM_FAILURE;
197 			goto fail;
198 		}
199 		IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
200 	}
201 
202 	IPACMDBG("soft-routing ipv4 flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl);
203 		/* copy filter hdls */
204 		software_routing_fl_rule_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl;
205 
206 		/* handle v6*/
207 		m_pFilteringTable->ip = IPA_IP_v6;
208 	if (mhip)
209 	{
210 		/* generate eq */
211 		memset(&flt_eq, 0, sizeof(flt_eq));
212 		memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
213 		flt_eq.ip = IPA_IP_v6;
214 
215 		if(0 != ioctl(fd, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) //define and cpy attribute to this struct
216 		{
217 			IPACMERR("Failed to get eq_attrib\n");
218 			res = IPACM_FAILURE;
219 			goto fail;
220 		}
221 		memcpy(&flt_rule_entry.rule.eq_attrib,
222 			&flt_eq.eq_attrib,
223 			sizeof(flt_rule_entry.rule.eq_attrib));
224 		memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
225 
226 		/* add rule */
227 		if(false == m_filtering.AddOffloadFilteringRule(m_pFilteringTable, IPACM_Iface::ipacmcfg->GetQmapId(), 1))
228 		{
229 			IPACMERR("Failed to install WAN DL filtering table.\n");
230 			res = IPACM_FAILURE;
231 			goto fail;
232 		}
233 	}
234 	else
235 	{
236 		m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
237 		if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
238 		{
239 			IPACMERR("Error Adding Filtering rule, aborting...\n");
240 			res = IPACM_FAILURE;
241 			goto fail;
242 		}
243 		else if (m_pFilteringTable->rules[0].status)
244 		{
245 			IPACMERR("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status);
246 			res = IPACM_FAILURE;
247 			goto fail;
248 		}
249 		IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
250 	}
251 
252 	IPACMDBG("soft-routing ipv6 flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl);
253 		/* copy filter hdls */
254 			software_routing_fl_rule_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl;
255 		softwarerouting_act = true;
256 
257 fail:
258 	close(fd);
259 	if(m_pFilteringTable != NULL)
260 	{
261 	free(m_pFilteringTable);
262 	}
263 	return res;
264 }
265 
266 /* software routing disable */
handle_software_routing_disable(bool mhip)267 int IPACM_Iface::handle_software_routing_disable(bool mhip)
268 {
269 	int len, res = IPACM_SUCCESS;
270 	ipa_ioc_del_flt_rule *pFilteringTable = NULL;
271 	struct ipa_flt_rule_del flt_rule_entry;
272 
273 	if (rx_prop == NULL)
274 	{
275 		IPACMDBG("No rx properties registered for iface %s\n", dev_name);
276 		return IPACM_SUCCESS;
277 	}
278 
279 	if (softwarerouting_act == false)
280 	{
281 		IPACMDBG("already delete software_routing rule for (%s)iface ip-family %d\n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ip_type);
282 		return IPACM_SUCCESS;
283 	}
284 
285 	if(mhip)
286 	{
287 		len = sizeof(struct ipa_ioc_del_flt_rule) + sizeof(struct ipa_flt_rule_del);
288 		pFilteringTable = (struct ipa_ioc_del_flt_rule*)malloc(len);
289 		if (pFilteringTable == NULL)
290 		{
291 			IPACMERR("Error Locate ipa_ioc_del_flt_rule memory...\n");
292 			return IPACM_FAILURE;
293 		}
294 		memset(pFilteringTable, 0, len);
295 
296 		pFilteringTable->commit = 1;
297 		pFilteringTable->ip = IPA_IP_v4;
298 		pFilteringTable->num_hdls = (uint8_t)1;
299 
300 		if (software_routing_fl_rule_hdl[0] == 0)
301 		{
302 			IPACMERR("invalid ipv4_exception_hdl.\n");
303 			res = IPACM_FAILURE;
304 			goto fail;
305 		}
306 
307 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_del));
308 		flt_rule_entry.hdl = software_routing_fl_rule_hdl[0];
309 
310 		memcpy(&(pFilteringTable->hdl[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del));
311 
312 		if(false == m_filtering.DelOffloadFilteringRule(pFilteringTable))
313 		{
314 			IPACMERR("Failed to delete MHI ipv4 exception rule.\n");
315 			res = IPACM_FAILURE;
316 			goto fail;
317 		}
318 		software_routing_fl_rule_hdl[0] = 0;
319 	}
320 	else
321 	{
322 		/* ipv4 case */
323 		if (m_filtering.DeleteFilteringHdls(&software_routing_fl_rule_hdl[0],
324 																				IPA_IP_v4, 1) == false)
325 		{
326 			IPACMERR("Error Adding Filtering rule, aborting...\n");
327 			res = IPACM_FAILURE;
328 			goto fail;
329 		}
330 		}
331 	IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
332 
333 	if(mhip)
334 	{
335 		pFilteringTable->ip = IPA_IP_v6;
336 		if (software_routing_fl_rule_hdl[1] == 0)
337 		{
338 			IPACMERR("invalid ipv6_exception_hdl.\n");
339 			res = IPACM_FAILURE;
340 			goto fail;
341 		}
342 
343 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_del));
344 		flt_rule_entry.hdl = software_routing_fl_rule_hdl[1];
345 
346 		memcpy(&(pFilteringTable->hdl[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del));
347 
348 		if(false == m_filtering.DelOffloadFilteringRule(pFilteringTable))
349 		{
350 			IPACMERR("Failed to delete MHI ipv6 exception rule.\n");
351 			res = IPACM_FAILURE;
352 			goto fail;
353 		}
354 		software_routing_fl_rule_hdl[1] = 0;
355 		}
356 		else
357 		{
358 		/* ipv6 case */
359 		if (m_filtering.DeleteFilteringHdls(&software_routing_fl_rule_hdl[1],
360 																				IPA_IP_v6, 1) == false)
361 		{
362 			IPACMERR("Error Adding Filtering rule, aborting...\n");
363 			res = IPACM_FAILURE;
364 			goto fail;
365 		}
366 	}
367 	IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
368 		softwarerouting_act = false;
369 
370 fail:
371 	if(pFilteringTable != NULL)
372 	{
373 		free(pFilteringTable);
374 	}
375 	return res;
376 }
377 
378 /* Query ipa_interface_index by given linux interface_index */
iface_ipa_index_query(int interface_index)379 int IPACM_Iface::iface_ipa_index_query
380 (
381 	 int interface_index
382 )
383 {
384 	int fd;
385 	int link = INVALID_IFACE;
386 	int i = 0;
387 	struct ifreq ifr;
388 
389 
390 	if(IPACM_Iface::ipacmcfg->iface_table == NULL)
391 	{
392 		IPACMERR("Iface table in IPACM_Config is not available.\n");
393 		return link;
394 	}
395 
396 	/* Search known linux interface-index and map to IPA interface-index*/
397 	for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_ipa_interfaces; i++)
398 	{
399 		if (interface_index == IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index)
400 		{
401 			link = i;
402 			IPACMDBG("Interface (%s) found: linux(%d) ipa(%d) \n",
403 							 IPACM_Iface::ipacmcfg->iface_table[i].iface_name,
404 							 IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index,
405 							 link);
406 			return link;
407 			break;
408 		}
409 	}
410 
411 	/* Search/Configure linux interface-index and map it to IPA interface-index */
412 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
413 	{
414 		PERROR("get interface name socket create failed");
415 		return IPACM_FAILURE;
416 	}
417 
418 	memset(&ifr, 0, sizeof(struct ifreq));
419 
420 	ifr.ifr_ifindex = interface_index;
421 	IPACMDBG_H("Interface index %d\n", interface_index);
422 
423 	if (ioctl(fd, SIOCGIFNAME, &ifr) < 0)
424 	{
425 		PERROR("call_ioctl_on_dev: ioctl failed:");
426 		close(fd);
427 		return IPACM_FAILURE;
428 	}
429 	close(fd);
430 
431 	IPACMDBG_H("Received interface name %s\n", ifr.ifr_name);
432 	for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_ipa_interfaces; i++)
433 	{
434 		if (strncmp(ifr.ifr_name,
435 								IPACM_Iface::ipacmcfg->iface_table[i].iface_name,
436 								sizeof(IPACM_Iface::ipacmcfg->iface_table[i].iface_name)) == 0)
437 		{
438 			IPACMDBG_H("Interface (%s) linux(%d) mapped to ipa(%d) \n", ifr.ifr_name,
439 							 IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index, i);
440 
441 			link = i;
442 			IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index = interface_index;
443 			break;
444 		}
445 	}
446 
447 	return link;
448 }
449 
450 /* Query ipa_interface ipv4_addr by given linux interface_index */
iface_addr_query(int interface_index)451 void IPACM_Iface::iface_addr_query
452 (
453 	 int interface_index
454 )
455 {
456 	int fd;
457 	struct ifreq ifr;
458 	struct ifaddrs *myaddrs, *ifa;
459 	ipacm_cmd_q_data evt_data;
460 	ipacm_event_data_addr *data_addr;
461 	struct in_addr iface_ipv4;
462 
463 	/* use linux interface-index to find interface name */
464 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
465 	{
466 		PERROR("get interface name socket create failed");
467 		return ;
468 	}
469 
470 	memset(&ifr, 0, sizeof(struct ifreq));
471 
472 	ifr.ifr_ifindex = interface_index;
473 	IPACMDBG_H("Interface index %d\n", interface_index);
474 
475 	if (ioctl(fd, SIOCGIFNAME, &ifr) < 0)
476 	{
477 		PERROR("call_ioctl_on_dev: ioctl failed:");
478 		close(fd);
479 		return ;
480 	}
481 	IPACMDBG_H("Interface index %d name: %s\n", interface_index,ifr.ifr_name);
482 	close(fd);
483 
484 	/* query ipv4/v6 address */
485     if(getifaddrs(&myaddrs) != 0)
486 	{
487         IPACMERR("getifaddrs");
488 		return ;
489 	}
490 
491     for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
492     {
493         if (ifa->ifa_addr == NULL)
494             continue;
495         if (!(ifa->ifa_flags & IFF_UP))
496             continue;
497 
498 		if(strcmp(ifr.ifr_name,ifa->ifa_name) == 0) // find current iface
499 		{
500 			IPACMDBG_H("Internal post new_addr event for iface %s\n", ifa->ifa_name);
501 			switch (ifa->ifa_addr->sa_family)
502 			{
503 				case AF_INET:
504 				{
505 					struct sockaddr_in *s4 = (struct sockaddr_in *)ifa->ifa_addr;
506 					IPACMDBG_H("ipv4 address %s\n",inet_ntoa(s4->sin_addr));
507 					iface_ipv4 = s4->sin_addr;
508 					/* post new_addr event to command queue */
509 					data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
510 					if(data_addr == NULL)
511 					{
512 						IPACMERR("unable to allocate memory for event data_addr\n");
513 						freeifaddrs(myaddrs);
514 						return ;
515 					}
516 					memset(data_addr, 0, sizeof(ipacm_event_data_addr));
517 					data_addr->iptype = IPA_IP_v4;
518 					data_addr->if_index = interface_index;
519 					data_addr->ipv4_addr = 	iface_ipv4.s_addr;
520 					data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr);
521 					strlcpy(data_addr->iface_name, ifr.ifr_name, sizeof(data_addr->iface_name));
522 					IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, if name:%s, ipv4 addr:0x%x\n",
523 						data_addr->if_index,
524 						data_addr->iface_name,
525 						data_addr->ipv4_addr);
526 
527 					evt_data.event = IPA_ADDR_ADD_EVENT;
528 					evt_data.evt_data = data_addr;
529 					IPACM_EvtDispatcher::PostEvt(&evt_data);
530 					break;
531 				}
532 
533 				case AF_INET6:
534 				{
535 					struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ifa->ifa_addr;
536 					/* post new_addr event to command queue */
537 					data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
538 					if(data_addr == NULL)
539 					{
540 						IPACMERR("unable to allocate memory for event data_addr\n");
541 						freeifaddrs(myaddrs);
542 						return ;
543 					}
544 					memset(data_addr, 0, sizeof(ipacm_event_data_addr));
545 					data_addr->iptype = IPA_IP_v6;
546 					data_addr->if_index = interface_index;
547 					memcpy(data_addr->ipv6_addr,
548 									&s6->sin6_addr,
549 									sizeof(data_addr->ipv6_addr));
550 					data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]);
551 					data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]);
552 					data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]);
553 					data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]);
554 					strlcpy(data_addr->iface_name, ifr.ifr_name, sizeof(data_addr->iface_name));
555 					IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, if name:%s, ipv6 addr:0x%x:%x:%x:%x\n",
556 							data_addr->if_index,
557 							data_addr->iface_name,
558 							data_addr->ipv6_addr[0], data_addr->ipv6_addr[1], data_addr->ipv6_addr[2], data_addr->ipv6_addr[3]);
559 
560 					evt_data.event = IPA_ADDR_ADD_EVENT;
561 					evt_data.evt_data = data_addr;
562 					IPACM_EvtDispatcher::PostEvt(&evt_data);
563 					break;
564 				}
565 
566 				default:
567 					continue;
568 			}
569 		}
570 	}
571     freeifaddrs(myaddrs);
572 	return ;
573 }
574 
575 /*Query the IPA endpoint property */
query_iface_property(void)576 int IPACM_Iface::query_iface_property(void)
577 {
578 	int res = IPACM_SUCCESS, fd = 0;
579 	uint32_t cnt=0;
580 
581 	fd = open(DEVICE_NAME, O_RDWR);
582 	IPACMDBG("iface query-property \n");
583 	if (0 == fd)
584 	{
585 		IPACMERR("Failed opening %s.\n", DEVICE_NAME);
586 		return IPACM_FAILURE;
587 	}
588 
589 	iface_query = (struct ipa_ioc_query_intf *)
590 		 calloc(1, sizeof(struct ipa_ioc_query_intf));
591 	if(iface_query == NULL)
592 	{
593 		IPACMERR("Unable to allocate iface_query memory.\n");
594 		close(fd);
595 		return IPACM_FAILURE;
596 	}
597 	IPACMDBG_H("iface name %s\n", dev_name);
598 	memcpy(iface_query->name, dev_name, sizeof(dev_name));
599 
600 	if (ioctl(fd, IPA_IOC_QUERY_INTF, iface_query) < 0)
601 	{
602 		PERROR("ioctl IPA_IOC_QUERY_INTF failed\n");
603 		/* iface_query memory will free when iface-down*/
604 		res = IPACM_FAILURE;
605 	}
606 
607 	if(iface_query->num_tx_props > 0)
608 	{
609 		tx_prop = (struct ipa_ioc_query_intf_tx_props *)
610 			 calloc(1, sizeof(struct ipa_ioc_query_intf_tx_props) +
611 							iface_query->num_tx_props * sizeof(struct ipa_ioc_tx_intf_prop));
612 		if(tx_prop == NULL)
613 		{
614 			IPACMERR("Unable to allocate tx_prop memory.\n");
615 			close(fd);
616 			return IPACM_FAILURE;
617 		}
618 		memcpy(tx_prop->name, dev_name, sizeof(tx_prop->name));
619 		tx_prop->num_tx_props = iface_query->num_tx_props;
620 
621 		if (ioctl(fd, IPA_IOC_QUERY_INTF_TX_PROPS, tx_prop) < 0)
622 		{
623 			PERROR("ioctl IPA_IOC_QUERY_INTF_TX_PROPS failed\n");
624 			/* tx_prop memory will free when iface-down*/
625 			res = IPACM_FAILURE;
626 		}
627 
628 		if (res != IPACM_FAILURE)
629 		{
630 			for (cnt = 0; cnt < tx_prop->num_tx_props; cnt++)
631 			{
632 				IPACMDBG_H("Tx(%d):attrib-mask:0x%x, ip-type: %d, dst_pipe: %d, alt_dst_pipe: %d, header: %s\n",
633 						cnt, tx_prop->tx[cnt].attrib.attrib_mask,
634 						tx_prop->tx[cnt].ip, tx_prop->tx[cnt].dst_pipe,
635 						tx_prop->tx[cnt].alt_dst_pipe,
636 						tx_prop->tx[cnt].hdr_name);
637 
638 				if (tx_prop->tx[cnt].dst_pipe == 0)
639 				{
640 					IPACMERR("Tx(%d): wrong tx property: dst_pipe: 0.\n", cnt);
641 					close(fd);
642 					return IPACM_FAILURE;
643 				}
644 				if (tx_prop->tx[cnt].alt_dst_pipe == 0 &&
645 					((memcmp(dev_name, "wlan0", sizeof("wlan0")) == 0) ||
646 					(memcmp(dev_name, "wlan1", sizeof("wlan1")) == 0)))
647 				{
648 					IPACMERR("Tx(%d): wrong tx property: alt_dst_pipe: 0. \n", cnt);
649 					close(fd);
650 					return IPACM_FAILURE;
651 				}
652 
653 			}
654 		}
655 
656 	}
657 
658 	if (iface_query->num_rx_props > 0)
659 	{
660 		rx_prop = (struct ipa_ioc_query_intf_rx_props *)
661 			 calloc(1, sizeof(struct ipa_ioc_query_intf_rx_props) +
662 							iface_query->num_rx_props * sizeof(struct ipa_ioc_rx_intf_prop));
663 		if(rx_prop == NULL)
664 		{
665 			IPACMERR("Unable to allocate rx_prop memory.\n");
666 			close(fd);
667 			return IPACM_FAILURE;
668 		}
669 		memcpy(rx_prop->name, dev_name,
670 				 sizeof(rx_prop->name));
671 		rx_prop->num_rx_props = iface_query->num_rx_props;
672 
673 		if (ioctl(fd, IPA_IOC_QUERY_INTF_RX_PROPS, rx_prop) < 0)
674 		{
675 			PERROR("ioctl IPA_IOC_QUERY_INTF_RX_PROPS failed\n");
676 			/* rx_prop memory will free when iface-down*/
677 			res = IPACM_FAILURE;
678 		}
679 
680 		if (res != IPACM_FAILURE)
681 		{
682 			for (cnt = 0; cnt < rx_prop->num_rx_props; cnt++)
683 			{
684 				IPACMDBG_H("Rx(%d):attrib-mask:0x%x, ip-type: %d, src_pipe: %d\n",
685 								 cnt, rx_prop->rx[cnt].attrib.attrib_mask, rx_prop->rx[cnt].ip, rx_prop->rx[cnt].src_pipe);
686 			}
687 		}
688 	}
689 
690 	close(fd);
691 	return res;
692 }
693 
694 /*Configure the initial filter rules */
init_fl_rule(ipa_ip_type iptype)695 int IPACM_Iface::init_fl_rule(ipa_ip_type iptype)
696 {
697 
698 	int res = IPACM_SUCCESS, len = 0;
699 	struct ipa_flt_rule_add flt_rule_entry;
700 	ipa_ioc_add_flt_rule *m_pFilteringTable;
701 	bool result;
702 
703   /* Adding this hack because WLAN may not registered for Rx-endpoint, other ifaces will always have*/
704 	const char *dev_wlan0="wlan0";
705 	const char *dev_wlan1="wlan1";
706 	const char *dev_ecm0="ecm0";
707 
708     /* ADD corresponding ipa_rm_resource_name of RX-endpoint before adding all IPV4V6 FT-rules */
709 	if((IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat== WAN_IF) || (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat== EMBMS_IF))
710 	{
711 		IPACMDBG_H(" NOT add producer dependency on dev %s with registered rx-prop cat:%d \n", dev_name, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat);
712 	}
713 	else
714 	{
715 		if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_None && IPACM_Iface::ipacmcfg->GetIPAVer() < IPA_HW_v4_0)
716 		{
717 			if(rx_prop != NULL)
718 			{
719 				IPACMDBG_H("dev %s add producer dependency\n", dev_name);
720 				IPACMDBG_H("depend Got pipe %d rm index : %d \n", rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]);
721 				IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe],false);
722 			}
723 			else
724 			{
725 				/* only wlan may take software-path, not register Rx-property*/
726 				if(strcmp(dev_name,dev_wlan0) == 0 || strcmp(dev_name,dev_wlan1) == 0)
727 				{
728 					IPACMDBG_H("dev %s add producer dependency\n", dev_name);
729 					IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_HSIC_PROD);
730 					IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_HSIC_PROD,true);
731 				}
732 				if(strcmp(dev_name,dev_ecm0) == 0)
733 				{
734 					IPACMDBG_H("dev %s add producer dependency\n", dev_name);
735 					IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_USB_PROD);
736 					IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_USB_PROD,true);
737 				}
738 			}
739 		}
740 	}
741 	if (rx_prop == NULL)
742 	{
743 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
744 		return IPACM_SUCCESS;
745 	}
746 
747 	/* construct ipa_ioc_add_flt_rule with default filter rules */
748 	if (iptype == IPA_IP_v4)
749 	{
750 		len = sizeof(struct ipa_ioc_add_flt_rule) +
751 			 (IPV4_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add));
752 
753 		m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
754 		if (!m_pFilteringTable)
755 		{
756 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
757 			return IPACM_FAILURE;
758 		}
759 
760 		m_pFilteringTable->commit = 1;
761 		m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
762 		m_pFilteringTable->global = false;
763 		m_pFilteringTable->ip = iptype;
764 		m_pFilteringTable->num_rules = (uint8_t)IPV4_DEFAULT_FILTERTING_RULES;
765 
766 		/* Configuring Fragment Filtering Rule */
767 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
768 
769 		flt_rule_entry.rule.retain_hdr = 1;
770 		flt_rule_entry.at_rear = true;
771 		flt_rule_entry.flt_rule_hdl = -1;
772 		flt_rule_entry.status = -1;
773 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
774 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
775 		{
776 			flt_rule_entry.at_rear = false;
777 			flt_rule_entry.rule.hashable = false;
778 		}
779 		IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
780 		memcpy(&flt_rule_entry.rule.attrib,
781 					 &rx_prop->rx[0].attrib,
782 					 sizeof(flt_rule_entry.rule.attrib));
783 
784 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
785 		memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
786 
787 		/* Configuring Multicast Filtering Rule */
788 		memcpy(&flt_rule_entry.rule.attrib,
789 					 &rx_prop->rx[0].attrib,
790 					 sizeof(flt_rule_entry.rule.attrib));
791 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
792 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xF0000000;
793 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000;
794 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
795 		{
796 			flt_rule_entry.at_rear = true;
797 			flt_rule_entry.rule.hashable = true;
798 		}
799 		memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
800 
801 		/* Configuring Broadcast Filtering Rule */
802 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
803 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF;
804 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
805 		{
806 			flt_rule_entry.at_rear = true;
807 			flt_rule_entry.rule.hashable = true;
808 		}
809 		memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
810 
811 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
812 		/* use index hw-counter */
813 		if(ipa_if_cate == WAN_IF && IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
814 		{
815 			IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
816 			result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
817 		} else if(ipa_if_cate == WLAN_IF && IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
818 		{
819 			IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL);
820 			result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL);
821 		} else
822 		{
823 			result = m_filtering.AddFilteringRule(m_pFilteringTable);
824 		}
825 #else
826 		result = m_filtering.AddFilteringRule(m_pFilteringTable);
827 #endif
828 
829 		if (result == false)
830 		{
831 			IPACMERR("Error Adding Filtering rule, aborting...\n");
832 			res = IPACM_FAILURE;
833 			goto fail;
834 		}
835 		else
836 		{
837 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES);
838 			/* copy filter hdls */
839 			for (int i = 0; i < IPV4_DEFAULT_FILTERTING_RULES; i++)
840 			{
841 				if (m_pFilteringTable->rules[i].status == 0)
842 				{
843 					dft_v4fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl;
844 					IPACMDBG_H("Default v4 filter Rule %d HDL:0x%x\n", i, dft_v4fl_rule_hdl[i]);
845 				}
846 				else
847 				{
848 					IPACMERR("Failed adding default v4 Filtering rule %d\n", i);
849 				}
850 			}
851 		}
852 	}
853 	else
854 	{
855 		len = sizeof(struct ipa_ioc_add_flt_rule) +
856 			 (IPV6_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add));
857 
858 		m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
859 		if (!m_pFilteringTable)
860 		{
861 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
862 			return IPACM_FAILURE;
863 		}
864 
865 		m_pFilteringTable->commit = 1;
866 		m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
867 		m_pFilteringTable->global = false;
868 		m_pFilteringTable->ip = iptype;
869 		m_pFilteringTable->num_rules = (uint8_t)IPV6_DEFAULT_FILTERTING_RULES;
870 
871 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
872 
873 		flt_rule_entry.rule.retain_hdr = 1;
874 		flt_rule_entry.at_rear = true;
875 		flt_rule_entry.flt_rule_hdl = -1;
876 		flt_rule_entry.status = -1;
877 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
878 		/* Configuring Multicast Filtering Rule */
879 		memcpy(&flt_rule_entry.rule.attrib,
880 					 &rx_prop->rx[0].attrib,
881 					 sizeof(flt_rule_entry.rule.attrib));
882 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
883 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
884 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
885 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
886 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
887 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF000000;
888 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
889 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
890 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
891 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
892 		{
893 			flt_rule_entry.at_rear = true;
894 			flt_rule_entry.rule.hashable = true;
895 		}
896 		memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
897 
898 		/* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */
899 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
900 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
901 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
902 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
903 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFE800000;
904 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
905 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
906 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
907 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
908 		{
909 			flt_rule_entry.at_rear = true;
910 			flt_rule_entry.rule.hashable = true;
911 		}
912 		memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
913 
914 		/* Configuring fec0::/10 Reserved by IETF Filtering Rule */
915 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
916 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
917 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
918 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
919 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFEC00000;
920 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
921 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
922 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
923 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
924 		{
925 			flt_rule_entry.at_rear = true;
926 			flt_rule_entry.rule.hashable = true;
927 		}
928 		memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
929 
930 		/* Configuring fd00::/8 Unique Local Ipv6 Address */
931 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
932 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
933 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
934 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
935 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFD000000;
936 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
937 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
938 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
939 		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
940 		{
941 			flt_rule_entry.at_rear = true;
942 			flt_rule_entry.rule.hashable = true;
943 		}
944 		memcpy(&(m_pFilteringTable->rules[3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
945 
946 #ifdef FEATURE_IPA_ANDROID
947 		/* Add the ipv6 tcp/udp fragment filtering rule for MTU */
948 
949 		IPACMDBG_H("Adding IPv6 fragment filter rule\n");
950 
951 		flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_DST_ADDR);
952 
953 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
954 
955 		memcpy(&(m_pFilteringTable->rules[4]), &flt_rule_entry,
956 			sizeof(struct ipa_flt_rule_add));
957 
958 #endif
959 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
960 		/* use index hw-counter */
961 		if(ipa_if_cate == WAN_IF && IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
962 		{
963 			IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL);
964 			result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL);
965 		} else {
966 			result = m_filtering.AddFilteringRule(m_pFilteringTable);
967 		}
968 #else
969 		result = m_filtering.AddFilteringRule(m_pFilteringTable);
970 #endif
971 
972 		if (result == false)
973 		{
974 			IPACMERR("Error Adding Filtering rule, aborting...\n");
975 			res = IPACM_FAILURE;
976 			goto fail;
977 		}
978 		else
979 		{
980 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES);
981 			/* copy filter hdls */
982 			for (int i = 0;
983 					 i < IPV6_DEFAULT_FILTERTING_RULES;
984 					 i++)
985 			{
986 				if (m_pFilteringTable->rules[i].status == 0)
987 				{
988 					dft_v6fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl;
989 					IPACMDBG_H("Default v6 Filter Rule %d HDL:0x%x\n", i, dft_v6fl_rule_hdl[i]);
990 				}
991 				else
992 				{
993 					IPACMERR("Failing adding v6 default IPV6 rule %d\n", i);
994 				}
995 			}
996 		}
997 	}
998 
999 	/* Add Natting iface to IPACM_Config if there is  Rx/Tx property */
1000 	if (rx_prop != NULL || tx_prop != NULL)
1001 	{
1002 		IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING for ip-family %d \n", dev_name, iptype);
1003 		IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name, iptype);
1004 	}
1005 
1006 fail:
1007 	free(m_pFilteringTable);
1008 
1009 	return res;
1010 }
1011 
1012 /*  get ipa interface index from name */
ipa_get_if_index(char * if_name,int * if_index)1013 int IPACM_Iface::ipa_get_if_index
1014 (
1015   char * if_name,
1016   int * if_index
1017 )
1018 {
1019 	int fd;
1020 	struct ifreq ifr;
1021 
1022 	if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1023 	{
1024 		IPACMERR("get interface index socket create failed \n");
1025 		return IPACM_FAILURE;
1026 	}
1027 
1028 	if(strlen(if_name) >= sizeof(ifr.ifr_name))
1029 	{
1030 		IPACMERR("interface name overflows: len %zu\n", strlen(if_name));
1031 		close(fd);
1032 		return IPACM_FAILURE;
1033 	}
1034 
1035 	memset(&ifr, 0, sizeof(struct ifreq));
1036 	(void)strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
1037 	IPACMDBG_H("interface name (%s)\n", if_name);
1038 
1039 	if(ioctl(fd,SIOCGIFINDEX , &ifr) < 0)
1040 	{
1041 		IPACMERR("call_ioctl_on_dev: ioctl failed, interface name (%s):\n", ifr.ifr_name);
1042 		close(fd);
1043 		return IPACM_FAILURE;
1044 	}
1045 
1046 	*if_index = ifr.ifr_ifindex;
1047 	IPACMDBG_H("Interface index %d\n", *if_index);
1048 	close(fd);
1049 	return IPACM_SUCCESS;
1050 }
1051 
config_ip_type(ipa_ip_type iptype)1052 void IPACM_Iface::config_ip_type(ipa_ip_type iptype)
1053 {
1054 	/* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/
1055 	if (iptype == IPA_IP_v4)
1056 	{
1057 		if ((ip_type == IPA_IP_v4) || (ip_type == IPA_IP_MAX))
1058 		{
1059 			IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
1060 			return;
1061 		}
1062 
1063 		if (ip_type == IPA_IP_v6)
1064 		{
1065 			ip_type = IPA_IP_MAX;
1066 		}
1067 		else
1068 		{
1069 			ip_type = IPA_IP_v4;
1070 		}
1071 		IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
1072 	}
1073 	else
1074 	{
1075 		if ((ip_type == IPA_IP_v6) || (ip_type == IPA_IP_MAX))
1076 		{
1077 			IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
1078 			return;
1079 		}
1080 
1081 		if (ip_type == IPA_IP_v4)
1082 		{
1083 			ip_type = IPA_IP_MAX;
1084 		}
1085 		else
1086 		{
1087 			ip_type = IPA_IP_v6;
1088 		}
1089 
1090 		IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
1091 	}
1092 
1093 	return;
1094 }
1095 
change_to_network_order(ipa_ip_type iptype,ipa_rule_attrib * attrib)1096 void IPACM_Iface::change_to_network_order(ipa_ip_type iptype, ipa_rule_attrib* attrib)
1097 {
1098 	if(attrib == NULL)
1099 	{
1100 		IPACMERR("Attribute pointer is NULL.\n");
1101 		return;
1102 	}
1103 
1104 	if(iptype == IPA_IP_v6)
1105 	{
1106 		int i;
1107 		for(i=0; i<4; i++)
1108 		{
1109 			attrib->u.v6.src_addr[i] = htonl(attrib->u.v6.src_addr[i]);
1110 			attrib->u.v6.src_addr_mask[i] = htonl(attrib->u.v6.src_addr_mask[i]);
1111 			attrib->u.v6.dst_addr[i] = htonl(attrib->u.v6.dst_addr[i]);
1112 			attrib->u.v6.dst_addr_mask[i] = htonl(attrib->u.v6.dst_addr_mask[i]);
1113 		}
1114 	}
1115 	else
1116 	{
1117 		IPACMDBG_H("IP type is not IPv6, do nothing: %d\n", iptype);
1118 	}
1119 
1120 	return;
1121 }
1122 
is_global_ipv6_addr(uint32_t * ipv6_addr)1123 bool IPACM_Iface::is_global_ipv6_addr(uint32_t* ipv6_addr)
1124 {
1125 	uint32_t ipv6_link_local_prefix, ipv6_link_local_prefix_mask;
1126 	ipv6_link_local_prefix = 0xFE800000;
1127 	ipv6_link_local_prefix_mask = 0xFFC00000;
1128 
1129 	if(ipv6_addr == NULL)
1130 	{
1131 		IPACMERR("IPv6 address is empty.\n");
1132 		return false;
1133 	}
1134 	IPACMDBG_H("Get ipv6 address with first word 0x%08x.\n", ipv6_addr[0]);
1135 
1136 	if((ipv6_addr[0] & ipv6_link_local_prefix_mask) == (ipv6_link_local_prefix & ipv6_link_local_prefix_mask))
1137 	{
1138 		IPACMDBG_H("This IPv6 address is link local.\n");
1139 		return false;
1140 	}
1141 	else
1142 	{
1143 		IPACMDBG_H("This IPv6 address is not link local.\n");
1144 		return true;
1145 	}
1146 }
1147 
delete_iface(void)1148 void IPACM_Iface::delete_iface(void)
1149 {
1150 	IPACMDBG_H("netdev (%s):ipa_index (%d) instance close \n",
1151 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num);
1152 	delete this;
1153 }
1154