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(rx_prop != NULL)
650 		{
651 			IPACMDBG_H("dev %s add producer dependency\n", dev_name);
652 			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]);
653 			IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe],false);
654 		}
655 		else
656 		{
657 			/* only wlan may take software-path, not register Rx-property*/
658 			if(strcmp(dev_name,dev_wlan0) == 0 || strcmp(dev_name,dev_wlan1) == 0)
659 			{
660 				IPACMDBG_H("dev %s add producer dependency\n", dev_name);
661 				IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_HSIC_PROD);
662 				IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_HSIC_PROD,true);
663 			}
664 			if(strcmp(dev_name,dev_ecm0) == 0)
665 			{
666 				IPACMDBG_H("dev %s add producer dependency\n", dev_name);
667 				IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_USB_PROD);
668 				IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_USB_PROD,true);
669 			}
670 		}
671 	}
672 	if (rx_prop == NULL)
673 	{
674 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
675 		return IPACM_SUCCESS;
676 	}
677 
678 	/* construct ipa_ioc_add_flt_rule with default filter rules */
679 	if (iptype == IPA_IP_v4)
680 	{
681 		len = sizeof(struct ipa_ioc_add_flt_rule) +
682 			 (IPV4_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add));
683 
684 		m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
685 		if (!m_pFilteringTable)
686 		{
687 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
688 			return IPACM_FAILURE;
689 		}
690 
691 		m_pFilteringTable->commit = 1;
692 		m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
693 		m_pFilteringTable->global = false;
694 		m_pFilteringTable->ip = iptype;
695 		m_pFilteringTable->num_rules = (uint8_t)IPV4_DEFAULT_FILTERTING_RULES;
696 
697 		/* Configuring Fragment Filtering Rule */
698 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
699 
700 		flt_rule_entry.rule.retain_hdr = 1;
701 		flt_rule_entry.at_rear = true;
702 		flt_rule_entry.flt_rule_hdl = -1;
703 		flt_rule_entry.status = -1;
704 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
705 #ifdef FEATURE_IPA_V3
706 		flt_rule_entry.at_rear = false;
707 		flt_rule_entry.rule.hashable = false;
708 #endif
709 		IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
710 		memcpy(&flt_rule_entry.rule.attrib,
711 					 &rx_prop->rx[0].attrib,
712 					 sizeof(flt_rule_entry.rule.attrib));
713 
714 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
715 		memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
716 
717 		/* Configuring Multicast Filtering Rule */
718 		memcpy(&flt_rule_entry.rule.attrib,
719 					 &rx_prop->rx[0].attrib,
720 					 sizeof(flt_rule_entry.rule.attrib));
721 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
722 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xF0000000;
723 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000;
724 #ifdef FEATURE_IPA_V3
725 		flt_rule_entry.at_rear = true;
726 		flt_rule_entry.rule.hashable = true;
727 #endif
728 		memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
729 
730 		/* Configuring Broadcast Filtering Rule */
731 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
732 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF;
733 #ifdef FEATURE_IPA_V3
734 		flt_rule_entry.at_rear = true;
735 		flt_rule_entry.rule.hashable = true;
736 #endif
737 		memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
738 
739 		if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
740 		{
741 			IPACMERR("Error Adding Filtering rule, aborting...\n");
742 			res = IPACM_FAILURE;
743 			goto fail;
744 		}
745 		else
746 		{
747 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES);
748 			/* copy filter hdls */
749 			for (int i = 0; i < IPV4_DEFAULT_FILTERTING_RULES; i++)
750 			{
751 				if (m_pFilteringTable->rules[i].status == 0)
752 				{
753 					dft_v4fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl;
754 					IPACMDBG_H("Default v4 filter Rule %d HDL:0x%x\n", i, dft_v4fl_rule_hdl[i]);
755 				}
756 				else
757 				{
758 					IPACMERR("Failed adding default v4 Filtering rule %d\n", i);
759 				}
760 			}
761 		}
762 	}
763 	else
764 	{
765 		len = sizeof(struct ipa_ioc_add_flt_rule) +
766 			 (IPV6_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add));
767 
768 		m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
769 		if (!m_pFilteringTable)
770 		{
771 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
772 			return IPACM_FAILURE;
773 		}
774 
775 		m_pFilteringTable->commit = 1;
776 		m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
777 		m_pFilteringTable->global = false;
778 		m_pFilteringTable->ip = iptype;
779 		m_pFilteringTable->num_rules = (uint8_t)IPV6_DEFAULT_FILTERTING_RULES;
780 
781 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
782 
783 		flt_rule_entry.rule.retain_hdr = 1;
784 		flt_rule_entry.at_rear = true;
785 		flt_rule_entry.flt_rule_hdl = -1;
786 		flt_rule_entry.status = -1;
787 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
788 		/* Configuring Multicast Filtering Rule */
789 		memcpy(&flt_rule_entry.rule.attrib,
790 					 &rx_prop->rx[0].attrib,
791 					 sizeof(flt_rule_entry.rule.attrib));
792 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
793 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
794 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
795 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
796 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
797 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF000000;
798 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
799 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
800 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
801 #ifdef FEATURE_IPA_V3
802 		flt_rule_entry.at_rear = true;
803 		flt_rule_entry.rule.hashable = true;
804 #endif
805 		memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
806 
807 		/* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */
808 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
809 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
810 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
811 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
812 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFE800000;
813 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
814 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
815 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
816 #ifdef FEATURE_IPA_V3
817 		flt_rule_entry.at_rear = true;
818 		flt_rule_entry.rule.hashable = true;
819 #endif
820 		memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
821 
822 		/* Configuring fec0::/10 Reserved by IETF Filtering Rule */
823 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
824 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
825 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
826 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
827 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFEC00000;
828 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
829 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
830 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
831 #ifdef FEATURE_IPA_V3
832 		flt_rule_entry.at_rear = true;
833 		flt_rule_entry.rule.hashable = true;
834 #endif
835 		memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
836 
837 		/* Configuring fd00::/8 Unique Local Ipv6 Address */
838 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
839 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
840 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
841 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
842 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFD000000;
843 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
844 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
845 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
846 #ifdef FEATURE_IPA_V3
847 		flt_rule_entry.at_rear = true;
848 		flt_rule_entry.rule.hashable = true;
849 #endif
850 		memcpy(&(m_pFilteringTable->rules[3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
851 
852 #ifdef FEATURE_IPA_ANDROID
853 		/* Add the ipv6 tcp fragment filtering rule. */
854 
855 		IPACMDBG_H("Adding IPv6 TCP fragment filter rule\n");
856 
857 		flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_DST_ADDR);
858 
859 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
860 		flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP;
861 
862 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
863 
864 		memcpy(&(m_pFilteringTable->rules[4]), &flt_rule_entry,
865 			sizeof(struct ipa_flt_rule_add));
866 
867 		IPACMDBG_H("Add TCP ctrl rules: total num %d\n", IPV6_DEFAULT_FILTERTING_RULES);
868 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
869 
870 		flt_rule_entry.at_rear = true;
871 		flt_rule_entry.flt_rule_hdl = -1;
872 		flt_rule_entry.status = -1;
873 
874 		flt_rule_entry.rule.retain_hdr = 1;
875 		flt_rule_entry.rule.to_uc = 0;
876 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
877 		flt_rule_entry.rule.eq_attrib_type = 1;
878 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap = 0;
879 
880 		if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA)
881 		{
882 #ifdef FEATURE_IPA_V3
883 			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<9);
884 #else
885 			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<14);
886 #endif
887 			flt_rule_entry.rule.eq_attrib.metadata_meq32_present = 1;
888 			flt_rule_entry.rule.eq_attrib.metadata_meq32.offset = 0;
889 			flt_rule_entry.rule.eq_attrib.metadata_meq32.value = rx_prop->rx[0].attrib.meta_data;
890 			flt_rule_entry.rule.eq_attrib.metadata_meq32.mask = rx_prop->rx[0].attrib.meta_data_mask;
891 		}
892 
893 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<1);
894 		flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1;
895 		flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP;
896 
897 #ifdef FEATURE_IPA_V3
898 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7);
899 #else
900 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8);
901 #endif
902 		flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1;
903 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12;
904 
905 		/* add TCP FIN rule*/
906 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_FIN_SHIFT);
907 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_FIN_SHIFT);
908 		memcpy(&(m_pFilteringTable->rules[5]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
909 
910 		/* add TCP SYN rule*/
911 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_SYN_SHIFT);
912 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_SYN_SHIFT);
913 		memcpy(&(m_pFilteringTable->rules[6]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
914 
915 		/* add TCP RST rule*/
916 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_RST_SHIFT);
917 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_RST_SHIFT);
918 		memcpy(&(m_pFilteringTable->rules[7]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
919 
920 #endif
921 		if (m_filtering.AddFilteringRule(m_pFilteringTable) == false)
922 		{
923 			IPACMERR("Error Adding Filtering rule, aborting...\n");
924 			res = IPACM_FAILURE;
925 			goto fail;
926 		}
927 		else
928 		{
929 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES);
930 			/* copy filter hdls */
931 			for (int i = 0;
932 					 i < IPV6_DEFAULT_FILTERTING_RULES;
933 					 i++)
934 			{
935 				if (m_pFilteringTable->rules[i].status == 0)
936 				{
937 					dft_v6fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl;
938 					IPACMDBG_H("Default v6 Filter Rule %d HDL:0x%x\n", i, dft_v6fl_rule_hdl[i]);
939 				}
940 				else
941 				{
942 					IPACMERR("Failing adding v6 default IPV6 rule %d\n", i);
943 				}
944 			}
945 		}
946 	}
947 
948 	/* Add Natting iface to IPACM_Config if there is  Rx/Tx property */
949 	if (rx_prop != NULL || tx_prop != NULL)
950 	{
951 		IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING for ip-family %d \n", dev_name, iptype);
952 		IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name, iptype);
953 	}
954 
955 fail:
956 	free(m_pFilteringTable);
957 
958 	return res;
959 }
960 
961 /*  get ipa interface name */
ipa_get_if_index(char * if_name,int * if_index)962 int IPACM_Iface::ipa_get_if_index
963 (
964   char * if_name,
965   int * if_index
966 )
967 {
968 	int fd;
969 	struct ifreq ifr;
970 
971 	if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
972 	{
973 		IPACMERR("get interface index socket create failed \n");
974 		return IPACM_FAILURE;
975 	}
976 
977 	if(strlen(if_name) >= sizeof(ifr.ifr_name))
978 	{
979 		IPACMERR("interface name overflows: len %zu\n", strlen(if_name));
980 		close(fd);
981 		return IPACM_FAILURE;
982 	}
983 
984 	memset(&ifr, 0, sizeof(struct ifreq));
985 	(void)strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
986 	IPACMDBG_H("interface name (%s)\n", if_name);
987 
988 	if(ioctl(fd,SIOCGIFINDEX , &ifr) < 0)
989 	{
990 		IPACMERR("call_ioctl_on_dev: ioctl failed, interface name (%s):\n", ifr.ifr_name);
991 		close(fd);
992 		return IPACM_FAILURE;
993 	}
994 
995 	*if_index = ifr.ifr_ifindex;
996 	IPACMDBG_H("Interface index %d\n", *if_index);
997 	close(fd);
998 	return IPACM_SUCCESS;
999 }
1000 
config_ip_type(ipa_ip_type iptype)1001 void IPACM_Iface::config_ip_type(ipa_ip_type iptype)
1002 {
1003 	/* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/
1004 	if (iptype == IPA_IP_v4)
1005 	{
1006 		if ((ip_type == IPA_IP_v4) || (ip_type == IPA_IP_MAX))
1007 		{
1008 			IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
1009 			return;
1010 		}
1011 
1012 		if (ip_type == IPA_IP_v6)
1013 		{
1014 			ip_type = IPA_IP_MAX;
1015 		}
1016 		else
1017 		{
1018 			ip_type = IPA_IP_v4;
1019 		}
1020 		IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
1021 	}
1022 	else
1023 	{
1024 		if ((ip_type == IPA_IP_v6) || (ip_type == IPA_IP_MAX))
1025 		{
1026 			IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
1027 			return;
1028 		}
1029 
1030 		if (ip_type == IPA_IP_v4)
1031 		{
1032 			ip_type = IPA_IP_MAX;
1033 		}
1034 		else
1035 		{
1036 			ip_type = IPA_IP_v6;
1037 		}
1038 
1039 		IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
1040 	}
1041 
1042 	return;
1043 }
1044 
delete_iface(void)1045 void IPACM_Iface::delete_iface(void)
1046 {
1047 	IPACMDBG_H("netdev (%s):ipa_index (%d) instance close \n",
1048 			IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num);
1049 	delete this;
1050 }
1051