1 /*
2 Copyright (c) 2013-2018, 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(void)91 int IPACM_Iface::handle_software_routing_enable(void)
92 {
93 
94 	int res = IPACM_SUCCESS;
95 	struct ipa_flt_rule_add flt_rule_entry;
96 	ipa_ioc_add_flt_rule *m_pFilteringTable;
97 
98 	IPACMDBG("\n");
99 	if (softwarerouting_act == true)
100 	{
101 		IPACMDBG("already setup software_routing rule for (%s)iface ip-family %d\n",
102 						     IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ip_type);
103 		return IPACM_SUCCESS;
104 	}
105 
106 	if(rx_prop == NULL)
107 	{
108 		IPACMDBG("No rx properties registered for iface %s\n", dev_name);
109 		return IPACM_SUCCESS;
110 	}
111 
112 	m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)
113 		 calloc(1,
114 						sizeof(struct ipa_ioc_add_flt_rule) +
115 						1 * sizeof(struct ipa_flt_rule_add)
116 						);
117 	if (!m_pFilteringTable)
118 	{
119 		IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
120 		return IPACM_FAILURE;
121 	}
122 
123 	m_pFilteringTable->commit = 1;
124 	m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
125 	m_pFilteringTable->global = false;
126 	m_pFilteringTable->num_rules = (uint8_t)1;
127 
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 #ifdef FEATURE_IPA_V3
137 	flt_rule_entry.rule.hashable = true;
138 #endif
139 	memcpy(&flt_rule_entry.rule.attrib,
140 				 &rx_prop->rx[0].attrib,
141 				 sizeof(flt_rule_entry.rule.attrib));
142 
143 	memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
144 
145 	/* check iface is v4 or v6 or both*/
146 //	if (ip_type == IPA_IP_MAX)
147 //	{
148 		/* handle v4 */
149 		m_pFilteringTable->ip = IPA_IP_v4;
150 		if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
151 		{
152 			IPACMERR("Error Adding Filtering rule, aborting...\n");
153 			res = IPACM_FAILURE;
154 			goto fail;
155 		}
156 		else if (m_pFilteringTable->rules[0].status)
157 		{
158 			IPACMERR("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status);
159 			res = IPACM_FAILURE;
160 			goto fail;
161 		}
162 
163 		IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
164 		IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl);
165 		/* copy filter hdls */
166 		software_routing_fl_rule_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl;
167 
168 
169 		/* handle v6*/
170 		m_pFilteringTable->ip = IPA_IP_v6;
171 		if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
172 		{
173 			IPACMERR("Error Adding Filtering rule, aborting...\n");
174 			res = IPACM_FAILURE;
175 			goto fail;
176 		}
177 		else if (m_pFilteringTable->rules[0].status)
178 		{
179 			IPACMDBG("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status);
180 			res = IPACM_FAILURE;
181 			goto fail;
182 		}
183 
184 		IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
185 		IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl);
186 		/* copy filter hdls */
187 		software_routing_fl_rule_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl;
188 		softwarerouting_act = true;
189 #if 0
190 	}
191 	else
192 	{
193 		if (ip_type == IPA_IP_v4)
194 		{
195 			m_pFilteringTable->ip = IPA_IP_v4;
196 		}
197 		else
198 		{
199 			m_pFilteringTable->ip = IPA_IP_v6;
200 		}
201 
202 		if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
203 		{
204 			IPACMERR("Error Adding Filtering rule, aborting...\n");
205 			res = IPACM_FAILURE;
206 			goto fail;
207 		}
208 		else if (m_pFilteringTable->rules[0].status)
209 		{
210 			IPACMERR("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status);
211 			res = IPACM_FAILURE;
212 			goto fail;
213 		}
214 
215 		IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, ip_type, 1);
216 		IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl);
217 		/* copy filter hdls */
218 		if (ip_type == IPA_IP_v4)
219 		{
220 			software_routing_fl_rule_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl;
221 		}
222 		else
223 		{
224 			software_routing_fl_rule_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl;
225 		}
226 		softwarerouting_act = true;
227 	}
228 #endif
229 
230 fail:
231 	free(m_pFilteringTable);
232 
233 	return res;
234 }
235 
236 /* software routing disable */
handle_software_routing_disable(void)237 int IPACM_Iface::handle_software_routing_disable(void)
238 {
239 	int res = IPACM_SUCCESS;
240 
241 	if (rx_prop == NULL)
242 	{
243 		IPACMDBG("No rx properties registered for iface %s\n", dev_name);
244 		return IPACM_SUCCESS;
245 	}
246 
247 	if (softwarerouting_act == false)
248 	{
249 		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);
250 		return IPACM_SUCCESS;
251 	}
252 
253 //	if (ip_type == IPA_IP_MAX)
254 //	{
255 		/* ipv4 case */
256 		if (m_filtering.DeleteFilteringHdls(&software_routing_fl_rule_hdl[0],
257 																				IPA_IP_v4, 1) == false)
258 		{
259 			IPACMERR("Error Adding Filtering rule, aborting...\n");
260 			res = IPACM_FAILURE;
261 			goto fail;
262 		}
263 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
264 
265 		/* ipv6 case */
266 		if (m_filtering.DeleteFilteringHdls(&software_routing_fl_rule_hdl[1],
267 																				IPA_IP_v6, 1) == false)
268 		{
269 			IPACMERR("Error Adding Filtering rule, aborting...\n");
270 			res = IPACM_FAILURE;
271 			goto fail;
272 		}
273 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
274 		softwarerouting_act = false;
275 #if 0
276 	}
277 	else
278 	{
279 		if (ip_type == IPA_IP_v4)
280 		{
281 			ip = IPA_IP_v4;
282 		}
283 		else
284 		{
285 			ip = IPA_IP_v6;
286 		}
287 
288 
289 		if (ip_type == IPA_IP_v4)
290 		{
291 			flt_hdl = software_routing_fl_rule_hdl[0];
292 		}
293 		else
294 		{
295 			flt_hdl = software_routing_fl_rule_hdl[1];
296 		}
297 
298 		if (m_filtering.DeleteFilteringHdls(&flt_hdl, ip, 1) == false)
299 		{
300 			IPACMERR("Error Adding Filtering rule, aborting...\n");
301 			res = IPACM_FAILURE;
302 			goto fail;
303 		}
304 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, ip, 1);
305 		softwarerouting_act = false;
306 	}
307 #endif
308 
309 fail:
310 	return res;
311 }
312 
313 /* Query ipa_interface_index by given linux interface_index */
iface_ipa_index_query(int interface_index)314 int IPACM_Iface::iface_ipa_index_query
315 (
316 	 int interface_index
317 )
318 {
319 	int fd;
320 	int link = INVALID_IFACE;
321 	int i = 0;
322 	struct ifreq ifr;
323 
324 
325 	if(IPACM_Iface::ipacmcfg->iface_table == NULL)
326 	{
327 		IPACMERR("Iface table in IPACM_Config is not available.\n");
328 		return link;
329 	}
330 
331 	/* Search known linux interface-index and map to IPA interface-index*/
332 	for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_ipa_interfaces; i++)
333 	{
334 		if (interface_index == IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index)
335 		{
336 			link = i;
337 			IPACMDBG("Interface (%s) found: linux(%d) ipa(%d) \n",
338 							 IPACM_Iface::ipacmcfg->iface_table[i].iface_name,
339 							 IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index,
340 							 link);
341 			return link;
342 			break;
343 		}
344 	}
345 
346 	/* Search/Configure linux interface-index and map it to IPA interface-index */
347 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
348 	{
349 		PERROR("get interface name socket create failed");
350 		return IPACM_FAILURE;
351 	}
352 
353 	memset(&ifr, 0, sizeof(struct ifreq));
354 
355 	ifr.ifr_ifindex = interface_index;
356 	IPACMDBG_H("Interface index %d\n", interface_index);
357 
358 	if (ioctl(fd, SIOCGIFNAME, &ifr) < 0)
359 	{
360 		PERROR("call_ioctl_on_dev: ioctl failed:");
361 		close(fd);
362 		return IPACM_FAILURE;
363 	}
364 	close(fd);
365 
366 	IPACMDBG_H("Received interface name %s\n", ifr.ifr_name);
367 	for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_ipa_interfaces; i++)
368 	{
369 		if (strncmp(ifr.ifr_name,
370 								IPACM_Iface::ipacmcfg->iface_table[i].iface_name,
371 								sizeof(IPACM_Iface::ipacmcfg->iface_table[i].iface_name)) == 0)
372 		{
373 			IPACMDBG_H("Interface (%s) linux(%d) mapped to ipa(%d) \n", ifr.ifr_name,
374 							 IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index, i);
375 
376 			link = i;
377 			IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index = interface_index;
378 			break;
379 		}
380 	}
381 
382 	return link;
383 }
384 
385 /* Query ipa_interface ipv4_addr by given linux interface_index */
iface_addr_query(int interface_index)386 void IPACM_Iface::iface_addr_query
387 (
388 	 int interface_index
389 )
390 {
391 	int fd;
392 	struct ifreq ifr;
393 	struct ifaddrs *myaddrs, *ifa;
394 	ipacm_cmd_q_data evt_data;
395 	ipacm_event_data_addr *data_addr;
396 	struct in_addr iface_ipv4;
397 
398 	/* use linux interface-index to find interface name */
399 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
400 	{
401 		PERROR("get interface name socket create failed");
402 		return ;
403 	}
404 
405 	memset(&ifr, 0, sizeof(struct ifreq));
406 
407 	ifr.ifr_ifindex = interface_index;
408 	IPACMDBG_H("Interface index %d\n", interface_index);
409 
410 	if (ioctl(fd, SIOCGIFNAME, &ifr) < 0)
411 	{
412 		PERROR("call_ioctl_on_dev: ioctl failed:");
413 		close(fd);
414 		return ;
415 	}
416 	IPACMDBG_H("Interface index %d name: %s\n", interface_index,ifr.ifr_name);
417 	close(fd);
418 
419 	/* query ipv4/v6 address */
420     if(getifaddrs(&myaddrs) != 0)
421 	{
422         IPACMERR("getifaddrs");
423 		return ;
424 	}
425 
426     for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
427     {
428         if (ifa->ifa_addr == NULL)
429             continue;
430         if (!(ifa->ifa_flags & IFF_UP))
431             continue;
432 
433 		if(strcmp(ifr.ifr_name,ifa->ifa_name) == 0) // find current iface
434 		{
435 			IPACMDBG_H("Internal post new_addr event for iface %s\n", ifa->ifa_name);
436 			switch (ifa->ifa_addr->sa_family)
437 			{
438 				case AF_INET:
439 				{
440 					struct sockaddr_in *s4 = (struct sockaddr_in *)ifa->ifa_addr;
441 					IPACMDBG_H("ipv4 address %s\n",inet_ntoa(s4->sin_addr));
442 					iface_ipv4 = s4->sin_addr;
443 					/* post new_addr event to command queue */
444 					data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
445 					if(data_addr == NULL)
446 					{
447 						IPACMERR("unable to allocate memory for event data_addr\n");
448 						freeifaddrs(myaddrs);
449 						return ;
450 					}
451 					memset(data_addr, 0, sizeof(ipacm_event_data_addr));
452 					data_addr->iptype = IPA_IP_v4;
453 					data_addr->if_index = interface_index;
454 					data_addr->ipv4_addr = 	iface_ipv4.s_addr;
455 					data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr);
456 					strlcpy(data_addr->iface_name, ifr.ifr_name, sizeof(data_addr->iface_name));
457 					IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, if name:%s, ipv4 addr:0x%x\n",
458 						data_addr->if_index,
459 						data_addr->iface_name,
460 						data_addr->ipv4_addr);
461 
462 					evt_data.event = IPA_ADDR_ADD_EVENT;
463 					evt_data.evt_data = data_addr;
464 					IPACM_EvtDispatcher::PostEvt(&evt_data);
465 					break;
466 				}
467 
468 				case AF_INET6:
469 				{
470 					struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ifa->ifa_addr;
471 					/* post new_addr event to command queue */
472 					data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
473 					if(data_addr == NULL)
474 					{
475 						IPACMERR("unable to allocate memory for event data_addr\n");
476 						freeifaddrs(myaddrs);
477 						return ;
478 					}
479 					memset(data_addr, 0, sizeof(ipacm_event_data_addr));
480 					data_addr->iptype = IPA_IP_v6;
481 					data_addr->if_index = interface_index;
482 					memcpy(data_addr->ipv6_addr,
483 									&s6->sin6_addr,
484 									sizeof(data_addr->ipv6_addr));
485 					data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]);
486 					data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]);
487 					data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]);
488 					data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]);
489 					strlcpy(data_addr->iface_name, ifr.ifr_name, sizeof(data_addr->iface_name));
490 					IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, if name:%s, ipv6 addr:0x%x:%x:%x:%x\n",
491 							data_addr->if_index,
492 							data_addr->iface_name,
493 							data_addr->ipv6_addr[0], data_addr->ipv6_addr[1], data_addr->ipv6_addr[2], data_addr->ipv6_addr[3]);
494 
495 					evt_data.event = IPA_ADDR_ADD_EVENT;
496 					evt_data.evt_data = data_addr;
497 					IPACM_EvtDispatcher::PostEvt(&evt_data);
498 					break;
499 				}
500 
501 				default:
502 					continue;
503 			}
504 		}
505 	}
506     freeifaddrs(myaddrs);
507 	return ;
508 }
509 
510 /*Query the IPA endpoint property */
query_iface_property(void)511 int IPACM_Iface::query_iface_property(void)
512 {
513 	int res = IPACM_SUCCESS, fd = 0;
514 	uint32_t cnt=0;
515 
516 	fd = open(DEVICE_NAME, O_RDWR);
517 	IPACMDBG("iface query-property \n");
518 	if (0 == fd)
519 	{
520 		IPACMERR("Failed opening %s.\n", DEVICE_NAME);
521 		return IPACM_FAILURE;
522 	}
523 
524 	iface_query = (struct ipa_ioc_query_intf *)
525 		 calloc(1, sizeof(struct ipa_ioc_query_intf));
526 	if(iface_query == NULL)
527 	{
528 		IPACMERR("Unable to allocate iface_query memory.\n");
529 		close(fd);
530 		return IPACM_FAILURE;
531 	}
532 	IPACMDBG_H("iface name %s\n", dev_name);
533 	memcpy(iface_query->name, dev_name, sizeof(dev_name));
534 
535 	if (ioctl(fd, IPA_IOC_QUERY_INTF, iface_query) < 0)
536 	{
537 		PERROR("ioctl IPA_IOC_QUERY_INTF failed\n");
538 		/* iface_query memory will free when iface-down*/
539 		res = IPACM_FAILURE;
540 	}
541 
542 	if(iface_query->num_tx_props > 0)
543 	{
544 		tx_prop = (struct ipa_ioc_query_intf_tx_props *)
545 			 calloc(1, sizeof(struct ipa_ioc_query_intf_tx_props) +
546 							iface_query->num_tx_props * sizeof(struct ipa_ioc_tx_intf_prop));
547 		if(tx_prop == NULL)
548 		{
549 			IPACMERR("Unable to allocate tx_prop memory.\n");
550 			close(fd);
551 			return IPACM_FAILURE;
552 		}
553 		memcpy(tx_prop->name, dev_name, sizeof(tx_prop->name));
554 		tx_prop->num_tx_props = iface_query->num_tx_props;
555 
556 		if (ioctl(fd, IPA_IOC_QUERY_INTF_TX_PROPS, tx_prop) < 0)
557 		{
558 			PERROR("ioctl IPA_IOC_QUERY_INTF_TX_PROPS failed\n");
559 			/* tx_prop memory will free when iface-down*/
560 			res = IPACM_FAILURE;
561 		}
562 
563 		if (res != IPACM_FAILURE)
564 		{
565 			for (cnt = 0; cnt < tx_prop->num_tx_props; cnt++)
566 			{
567 				IPACMDBG_H("Tx(%d):attrib-mask:0x%x, ip-type: %d, dst_pipe: %d, alt_dst_pipe: %d, header: %s\n",
568 						cnt, tx_prop->tx[cnt].attrib.attrib_mask,
569 						tx_prop->tx[cnt].ip, tx_prop->tx[cnt].dst_pipe,
570 						tx_prop->tx[cnt].alt_dst_pipe,
571 						tx_prop->tx[cnt].hdr_name);
572 
573 				if (tx_prop->tx[cnt].dst_pipe == 0)
574 				{
575 					IPACMERR("Tx(%d): wrong tx property: dst_pipe: 0.\n", cnt);
576 					close(fd);
577 					return IPACM_FAILURE;
578 				}
579 				if (tx_prop->tx[cnt].alt_dst_pipe == 0 &&
580 					((memcmp(dev_name, "wlan0", sizeof("wlan0")) == 0) ||
581 					(memcmp(dev_name, "wlan1", sizeof("wlan1")) == 0)))
582 				{
583 					IPACMERR("Tx(%d): wrong tx property: alt_dst_pipe: 0. \n", cnt);
584 					close(fd);
585 					return IPACM_FAILURE;
586 				}
587 
588 			}
589 		}
590 
591 	}
592 
593 	if (iface_query->num_rx_props > 0)
594 	{
595 		rx_prop = (struct ipa_ioc_query_intf_rx_props *)
596 			 calloc(1, sizeof(struct ipa_ioc_query_intf_rx_props) +
597 							iface_query->num_rx_props * sizeof(struct ipa_ioc_rx_intf_prop));
598 		if(rx_prop == NULL)
599 		{
600 			IPACMERR("Unable to allocate rx_prop memory.\n");
601 			close(fd);
602 			return IPACM_FAILURE;
603 		}
604 		memcpy(rx_prop->name, dev_name,
605 				 sizeof(rx_prop->name));
606 		rx_prop->num_rx_props = iface_query->num_rx_props;
607 
608 		if (ioctl(fd, IPA_IOC_QUERY_INTF_RX_PROPS, rx_prop) < 0)
609 		{
610 			PERROR("ioctl IPA_IOC_QUERY_INTF_RX_PROPS failed\n");
611 			/* rx_prop memory will free when iface-down*/
612 			res = IPACM_FAILURE;
613 		}
614 
615 		if (res != IPACM_FAILURE)
616 		{
617 			for (cnt = 0; cnt < rx_prop->num_rx_props; cnt++)
618 			{
619 				IPACMDBG_H("Rx(%d):attrib-mask:0x%x, ip-type: %d, src_pipe: %d\n",
620 								 cnt, rx_prop->rx[cnt].attrib.attrib_mask, rx_prop->rx[cnt].ip, rx_prop->rx[cnt].src_pipe);
621 			}
622 		}
623 	}
624 
625 	close(fd);
626 	return res;
627 }
628 
629 /*Configure the initial filter rules */
init_fl_rule(ipa_ip_type iptype)630 int IPACM_Iface::init_fl_rule(ipa_ip_type iptype)
631 {
632 
633 	int res = IPACM_SUCCESS, len = 0;
634 	struct ipa_flt_rule_add flt_rule_entry;
635 	ipa_ioc_add_flt_rule *m_pFilteringTable;
636 
637   /* Adding this hack because WLAN may not registered for Rx-endpoint, other ifaces will always have*/
638 	const char *dev_wlan0="wlan0";
639 	const char *dev_wlan1="wlan1";
640 	const char *dev_ecm0="ecm0";
641 
642     /* ADD corresponding ipa_rm_resource_name of RX-endpoint before adding all IPV4V6 FT-rules */
643 	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))
644 	{
645 		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);
646 	}
647 	else
648 	{
649 		if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_None && IPACM_Iface::ipacmcfg->GetIPAVer() < IPA_HW_v4_0)
650 		{
651 			if(rx_prop != NULL)
652 			{
653 				IPACMDBG_H("dev %s add producer dependency\n", dev_name);
654 				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]);
655 				IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe],false);
656 			}
657 			else
658 			{
659 				/* only wlan may take software-path, not register Rx-property*/
660 				if(strcmp(dev_name,dev_wlan0) == 0 || strcmp(dev_name,dev_wlan1) == 0)
661 				{
662 					IPACMDBG_H("dev %s add producer dependency\n", dev_name);
663 					IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_HSIC_PROD);
664 					IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_HSIC_PROD,true);
665 				}
666 				if(strcmp(dev_name,dev_ecm0) == 0)
667 				{
668 					IPACMDBG_H("dev %s add producer dependency\n", dev_name);
669 					IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_USB_PROD);
670 					IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_USB_PROD,true);
671 				}
672 			}
673 		}
674 	}
675 	if (rx_prop == NULL)
676 	{
677 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
678 		return IPACM_SUCCESS;
679 	}
680 
681 	/* construct ipa_ioc_add_flt_rule with default filter rules */
682 	if (iptype == IPA_IP_v4)
683 	{
684 		len = sizeof(struct ipa_ioc_add_flt_rule) +
685 			 (IPV4_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add));
686 
687 		m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
688 		if (!m_pFilteringTable)
689 		{
690 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
691 			return IPACM_FAILURE;
692 		}
693 
694 		m_pFilteringTable->commit = 1;
695 		m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
696 		m_pFilteringTable->global = false;
697 		m_pFilteringTable->ip = iptype;
698 		m_pFilteringTable->num_rules = (uint8_t)IPV4_DEFAULT_FILTERTING_RULES;
699 
700 		/* Configuring Fragment Filtering Rule */
701 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
702 
703 		flt_rule_entry.rule.retain_hdr = 1;
704 		flt_rule_entry.at_rear = true;
705 		flt_rule_entry.flt_rule_hdl = -1;
706 		flt_rule_entry.status = -1;
707 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
708 #ifdef FEATURE_IPA_V3
709 		flt_rule_entry.at_rear = false;
710 		flt_rule_entry.rule.hashable = false;
711 #endif
712 		IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
713 		memcpy(&flt_rule_entry.rule.attrib,
714 					 &rx_prop->rx[0].attrib,
715 					 sizeof(flt_rule_entry.rule.attrib));
716 
717 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
718 		memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
719 
720 		/* Configuring Multicast Filtering Rule */
721 		memcpy(&flt_rule_entry.rule.attrib,
722 					 &rx_prop->rx[0].attrib,
723 					 sizeof(flt_rule_entry.rule.attrib));
724 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
725 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xF0000000;
726 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000;
727 #ifdef FEATURE_IPA_V3
728 		flt_rule_entry.at_rear = true;
729 		flt_rule_entry.rule.hashable = true;
730 #endif
731 		memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
732 
733 		/* Configuring Broadcast Filtering Rule */
734 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
735 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF;
736 #ifdef FEATURE_IPA_V3
737 		flt_rule_entry.at_rear = true;
738 		flt_rule_entry.rule.hashable = true;
739 #endif
740 		memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
741 
742 		if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
743 		{
744 			IPACMERR("Error Adding Filtering rule, aborting...\n");
745 			res = IPACM_FAILURE;
746 			goto fail;
747 		}
748 		else
749 		{
750 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES);
751 			/* copy filter hdls */
752 			for (int i = 0; i < IPV4_DEFAULT_FILTERTING_RULES; i++)
753 			{
754 				if (m_pFilteringTable->rules[i].status == 0)
755 				{
756 					dft_v4fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl;
757 					IPACMDBG_H("Default v4 filter Rule %d HDL:0x%x\n", i, dft_v4fl_rule_hdl[i]);
758 				}
759 				else
760 				{
761 					IPACMERR("Failed adding default v4 Filtering rule %d\n", i);
762 				}
763 			}
764 		}
765 	}
766 	else
767 	{
768 		len = sizeof(struct ipa_ioc_add_flt_rule) +
769 			 (IPV6_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add));
770 
771 		m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
772 		if (!m_pFilteringTable)
773 		{
774 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
775 			return IPACM_FAILURE;
776 		}
777 
778 		m_pFilteringTable->commit = 1;
779 		m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
780 		m_pFilteringTable->global = false;
781 		m_pFilteringTable->ip = iptype;
782 		m_pFilteringTable->num_rules = (uint8_t)IPV6_DEFAULT_FILTERTING_RULES;
783 
784 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
785 
786 		flt_rule_entry.rule.retain_hdr = 1;
787 		flt_rule_entry.at_rear = true;
788 		flt_rule_entry.flt_rule_hdl = -1;
789 		flt_rule_entry.status = -1;
790 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
791 		/* Configuring Multicast Filtering Rule */
792 		memcpy(&flt_rule_entry.rule.attrib,
793 					 &rx_prop->rx[0].attrib,
794 					 sizeof(flt_rule_entry.rule.attrib));
795 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
796 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
797 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
798 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
799 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
800 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF000000;
801 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
802 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
803 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
804 #ifdef FEATURE_IPA_V3
805 		flt_rule_entry.at_rear = true;
806 		flt_rule_entry.rule.hashable = true;
807 #endif
808 		memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
809 
810 		/* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */
811 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
812 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
813 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
814 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
815 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFE800000;
816 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
817 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
818 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
819 #ifdef FEATURE_IPA_V3
820 		flt_rule_entry.at_rear = true;
821 		flt_rule_entry.rule.hashable = true;
822 #endif
823 		memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
824 
825 		/* Configuring fec0::/10 Reserved by IETF Filtering Rule */
826 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
827 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
828 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
829 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
830 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFEC00000;
831 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
832 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
833 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
834 #ifdef FEATURE_IPA_V3
835 		flt_rule_entry.at_rear = true;
836 		flt_rule_entry.rule.hashable = true;
837 #endif
838 		memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
839 
840 		/* Configuring fd00::/8 Unique Local Ipv6 Address */
841 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
842 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
843 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
844 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
845 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFD000000;
846 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
847 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
848 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
849 #ifdef FEATURE_IPA_V3
850 		flt_rule_entry.at_rear = true;
851 		flt_rule_entry.rule.hashable = true;
852 #endif
853 		memcpy(&(m_pFilteringTable->rules[3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
854 
855 #ifdef FEATURE_IPA_ANDROID
856 		/* Add the ipv6 tcp fragment filtering rule. */
857 
858 		IPACMDBG_H("Adding IPv6 TCP fragment filter rule\n");
859 
860 		flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_DST_ADDR);
861 
862 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
863 		flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP;
864 
865 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
866 
867 		memcpy(&(m_pFilteringTable->rules[4]), &flt_rule_entry,
868 			sizeof(struct ipa_flt_rule_add));
869 
870 		IPACMDBG_H("Add TCP ctrl rules: total num %d\n", IPV6_DEFAULT_FILTERTING_RULES);
871 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
872 
873 		flt_rule_entry.at_rear = true;
874 		flt_rule_entry.flt_rule_hdl = -1;
875 		flt_rule_entry.status = -1;
876 
877 		flt_rule_entry.rule.retain_hdr = 1;
878 		flt_rule_entry.rule.to_uc = 0;
879 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
880 		flt_rule_entry.rule.eq_attrib_type = 1;
881 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap = 0;
882 
883 		if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA)
884 		{
885 #ifdef FEATURE_IPA_V3
886 			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<9);
887 #else
888 			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<14);
889 #endif
890 			flt_rule_entry.rule.eq_attrib.metadata_meq32_present = 1;
891 			flt_rule_entry.rule.eq_attrib.metadata_meq32.offset = 0;
892 			flt_rule_entry.rule.eq_attrib.metadata_meq32.value = rx_prop->rx[0].attrib.meta_data;
893 			flt_rule_entry.rule.eq_attrib.metadata_meq32.mask = rx_prop->rx[0].attrib.meta_data_mask;
894 		}
895 
896 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<1);
897 		flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1;
898 		flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP;
899 
900 #ifdef FEATURE_IPA_V3
901 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7);
902 #else
903 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8);
904 #endif
905 		flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1;
906 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12;
907 
908 		/* add TCP FIN rule*/
909 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_FIN_SHIFT);
910 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_FIN_SHIFT);
911 		memcpy(&(m_pFilteringTable->rules[5]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
912 
913 		/* add TCP SYN rule*/
914 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_SYN_SHIFT);
915 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_SYN_SHIFT);
916 		memcpy(&(m_pFilteringTable->rules[6]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
917 
918 		/* add TCP RST rule*/
919 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_RST_SHIFT);
920 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_RST_SHIFT);
921 		memcpy(&(m_pFilteringTable->rules[7]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
922 
923 #endif
924 		if (m_filtering.AddFilteringRule(m_pFilteringTable) == false)
925 		{
926 			IPACMERR("Error Adding Filtering rule, aborting...\n");
927 			res = IPACM_FAILURE;
928 			goto fail;
929 		}
930 		else
931 		{
932 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES);
933 			/* copy filter hdls */
934 			for (int i = 0;
935 					 i < IPV6_DEFAULT_FILTERTING_RULES;
936 					 i++)
937 			{
938 				if (m_pFilteringTable->rules[i].status == 0)
939 				{
940 					dft_v6fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl;
941 					IPACMDBG_H("Default v6 Filter Rule %d HDL:0x%x\n", i, dft_v6fl_rule_hdl[i]);
942 				}
943 				else
944 				{
945 					IPACMERR("Failing adding v6 default IPV6 rule %d\n", i);
946 				}
947 			}
948 		}
949 	}
950 
951 	/* Add Natting iface to IPACM_Config if there is  Rx/Tx property */
952 	if (rx_prop != NULL || tx_prop != NULL)
953 	{
954 		IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING for ip-family %d \n", dev_name, iptype);
955 		IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name, iptype);
956 	}
957 
958 fail:
959 	free(m_pFilteringTable);
960 
961 	return res;
962 }
963 
964 /*  get ipa interface name */
ipa_get_if_index(char * if_name,int * if_index)965 int IPACM_Iface::ipa_get_if_index
966 (
967   char * if_name,
968   int * if_index
969 )
970 {
971 	int fd;
972 	struct ifreq ifr;
973 
974 	if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
975 	{
976 		IPACMERR("get interface index socket create failed \n");
977 		return IPACM_FAILURE;
978 	}
979 
980 	if(strlen(if_name) >= sizeof(ifr.ifr_name))
981 	{
982 		IPACMERR("interface name overflows: len %zu\n", strlen(if_name));
983 		close(fd);
984 		return IPACM_FAILURE;
985 	}
986 
987 	memset(&ifr, 0, sizeof(struct ifreq));
988 	(void)strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
989 	IPACMDBG_H("interface name (%s)\n", if_name);
990 
991 	if(ioctl(fd,SIOCGIFINDEX , &ifr) < 0)
992 	{
993 		IPACMERR("call_ioctl_on_dev: ioctl failed, interface name (%s):\n", ifr.ifr_name);
994 		close(fd);
995 		return IPACM_FAILURE;
996 	}
997 
998 	*if_index = ifr.ifr_ifindex;
999 	IPACMDBG_H("Interface index %d\n", *if_index);
1000 	close(fd);
1001 	return IPACM_SUCCESS;
1002 }
1003 
config_ip_type(ipa_ip_type iptype)1004 void IPACM_Iface::config_ip_type(ipa_ip_type iptype)
1005 {
1006 	/* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/
1007 	if (iptype == IPA_IP_v4)
1008 	{
1009 		if ((ip_type == IPA_IP_v4) || (ip_type == IPA_IP_MAX))
1010 		{
1011 			IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
1012 			return;
1013 		}
1014 
1015 		if (ip_type == IPA_IP_v6)
1016 		{
1017 			ip_type = IPA_IP_MAX;
1018 		}
1019 		else
1020 		{
1021 			ip_type = IPA_IP_v4;
1022 		}
1023 		IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
1024 	}
1025 	else
1026 	{
1027 		if ((ip_type == IPA_IP_v6) || (ip_type == IPA_IP_MAX))
1028 		{
1029 			IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
1030 			return;
1031 		}
1032 
1033 		if (ip_type == IPA_IP_v4)
1034 		{
1035 			ip_type = IPA_IP_MAX;
1036 		}
1037 		else
1038 		{
1039 			ip_type = IPA_IP_v6;
1040 		}
1041 
1042 		IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
1043 	}
1044 
1045 	return;
1046 }
1047 
delete_iface(void)1048 void IPACM_Iface::delete_iface(void)
1049 {
1050 	IPACMDBG_H("netdev (%s):ipa_index (%d) instance close \n",
1051 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num);
1052 	delete this;
1053 }
1054