Home | History | Annotate | Download | only in src
      1 /*
      2 Copyright (c) 2013, 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 
     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 */
     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 */
    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 */
    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 */
    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 					data_addr->iptype = IPA_IP_v4;
    452 					data_addr->if_index = interface_index;
    453 					data_addr->ipv4_addr = 	iface_ipv4.s_addr;
    454 					data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr);
    455 					IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv4 addr:0x%x\n",
    456 						data_addr->if_index,
    457 						data_addr->ipv4_addr);
    458 
    459 					evt_data.event = IPA_ADDR_ADD_EVENT;
    460 					evt_data.evt_data = data_addr;
    461 					IPACM_EvtDispatcher::PostEvt(&evt_data);
    462 					break;
    463 				}
    464 
    465 				case AF_INET6:
    466 				{
    467 					struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ifa->ifa_addr;
    468 					/* post new_addr event to command queue */
    469 					data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
    470 					if(data_addr == NULL)
    471 					{
    472 						IPACMERR("unable to allocate memory for event data_addr\n");
    473 						freeifaddrs(myaddrs);
    474 						return ;
    475 					}
    476 					data_addr->iptype = IPA_IP_v6;
    477 					data_addr->if_index = interface_index;
    478 					memcpy(data_addr->ipv6_addr,
    479 									&s6->sin6_addr,
    480 									sizeof(data_addr->ipv6_addr));
    481 					data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]);
    482 					data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]);
    483 					data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]);
    484 					data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]);
    485 					IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv6 addr:0x%x:%x:%x:%x\n",
    486 							data_addr->if_index,
    487 							data_addr->ipv6_addr[0], data_addr->ipv6_addr[1], data_addr->ipv6_addr[2], data_addr->ipv6_addr[3]);
    488 
    489 					evt_data.event = IPA_ADDR_ADD_EVENT;
    490 					evt_data.evt_data = data_addr;
    491 					IPACM_EvtDispatcher::PostEvt(&evt_data);
    492 					break;
    493 				}
    494 
    495 				default:
    496 					continue;
    497 			}
    498 		}
    499 	}
    500     freeifaddrs(myaddrs);
    501 	return ;
    502 }
    503 
    504 /*Query the IPA endpoint property */
    505 int IPACM_Iface::query_iface_property(void)
    506 {
    507 	int res = IPACM_SUCCESS, fd = 0;
    508 	uint32_t cnt=0;
    509 
    510 	fd = open(DEVICE_NAME, O_RDWR);
    511 	IPACMDBG("iface query-property \n");
    512 	if (0 == fd)
    513 	{
    514 		IPACMERR("Failed opening %s.\n", DEVICE_NAME);
    515 		return IPACM_FAILURE;
    516 	}
    517 
    518 	iface_query = (struct ipa_ioc_query_intf *)
    519 		 calloc(1, sizeof(struct ipa_ioc_query_intf));
    520 	if(iface_query == NULL)
    521 	{
    522 		IPACMERR("Unable to allocate iface_query memory.\n");
    523 		close(fd);
    524 		return IPACM_FAILURE;
    525 	}
    526 	IPACMDBG_H("iface name %s\n", dev_name);
    527 	memcpy(iface_query->name, dev_name, sizeof(dev_name));
    528 
    529 	if (ioctl(fd, IPA_IOC_QUERY_INTF, iface_query) < 0)
    530 	{
    531 		PERROR("ioctl IPA_IOC_QUERY_INTF failed\n");
    532 		/* iface_query memory will free when iface-down*/
    533 		res = IPACM_FAILURE;
    534 	}
    535 
    536 	if(iface_query->num_tx_props > 0)
    537 	{
    538 		tx_prop = (struct ipa_ioc_query_intf_tx_props *)
    539 			 calloc(1, sizeof(struct ipa_ioc_query_intf_tx_props) +
    540 							iface_query->num_tx_props * sizeof(struct ipa_ioc_tx_intf_prop));
    541 		if(tx_prop == NULL)
    542 		{
    543 			IPACMERR("Unable to allocate tx_prop memory.\n");
    544 			close(fd);
    545 			return IPACM_FAILURE;
    546 		}
    547 		memcpy(tx_prop->name, dev_name, sizeof(tx_prop->name));
    548 		tx_prop->num_tx_props = iface_query->num_tx_props;
    549 
    550 		if (ioctl(fd, IPA_IOC_QUERY_INTF_TX_PROPS, tx_prop) < 0)
    551 		{
    552 			PERROR("ioctl IPA_IOC_QUERY_INTF_TX_PROPS failed\n");
    553 			/* tx_prop memory will free when iface-down*/
    554 			res = IPACM_FAILURE;
    555 		}
    556 
    557 		if (res != IPACM_FAILURE)
    558 		{
    559 			for (cnt = 0; cnt < tx_prop->num_tx_props; cnt++)
    560 			{
    561 				IPACMDBG_H("Tx(%d):attrib-mask:0x%x, ip-type: %d, dst_pipe: %d, alt_dst_pipe: %d, header: %s\n",
    562 						cnt, tx_prop->tx[cnt].attrib.attrib_mask,
    563 						tx_prop->tx[cnt].ip, tx_prop->tx[cnt].dst_pipe,
    564 						tx_prop->tx[cnt].alt_dst_pipe,
    565 						tx_prop->tx[cnt].hdr_name);
    566 
    567 				if (tx_prop->tx[cnt].dst_pipe == 0)
    568 				{
    569 					IPACMERR("Tx(%d): wrong tx property: dst_pipe: 0.\n", cnt);
    570 					close(fd);
    571 					return IPACM_FAILURE;
    572 				}
    573 				if (tx_prop->tx[cnt].alt_dst_pipe == 0 &&
    574 					((memcmp(dev_name, "wlan0", sizeof("wlan0")) == 0) ||
    575 					(memcmp(dev_name, "wlan1", sizeof("wlan1")) == 0)))
    576 				{
    577 					IPACMERR("Tx(%d): wrong tx property: alt_dst_pipe: 0. \n", cnt);
    578 					close(fd);
    579 					return IPACM_FAILURE;
    580 				}
    581 
    582 			}
    583 		}
    584 
    585 	}
    586 
    587 	if (iface_query->num_rx_props > 0)
    588 	{
    589 		rx_prop = (struct ipa_ioc_query_intf_rx_props *)
    590 			 calloc(1, sizeof(struct ipa_ioc_query_intf_rx_props) +
    591 							iface_query->num_rx_props * sizeof(struct ipa_ioc_rx_intf_prop));
    592 		if(rx_prop == NULL)
    593 		{
    594 			IPACMERR("Unable to allocate rx_prop memory.\n");
    595 			close(fd);
    596 			return IPACM_FAILURE;
    597 		}
    598 		memcpy(rx_prop->name, dev_name,
    599 				 sizeof(rx_prop->name));
    600 		rx_prop->num_rx_props = iface_query->num_rx_props;
    601 
    602 		if (ioctl(fd, IPA_IOC_QUERY_INTF_RX_PROPS, rx_prop) < 0)
    603 		{
    604 			PERROR("ioctl IPA_IOC_QUERY_INTF_RX_PROPS failed\n");
    605 			/* rx_prop memory will free when iface-down*/
    606 			res = IPACM_FAILURE;
    607 		}
    608 
    609 		if (res != IPACM_FAILURE)
    610 		{
    611 			for (cnt = 0; cnt < rx_prop->num_rx_props; cnt++)
    612 			{
    613 				IPACMDBG_H("Rx(%d):attrib-mask:0x%x, ip-type: %d, src_pipe: %d\n",
    614 								 cnt, rx_prop->rx[cnt].attrib.attrib_mask, rx_prop->rx[cnt].ip, rx_prop->rx[cnt].src_pipe);
    615 			}
    616 		}
    617 	}
    618 
    619 	/* Add Natting iface to IPACM_Config if there is  Rx/Tx property */
    620 	if (rx_prop != NULL || tx_prop != NULL)
    621 	{
    622 		IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING \n", dev_name);
    623         IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name);
    624 	}
    625 
    626 	close(fd);
    627 	return res;
    628 }
    629 
    630 /*Configure the initial filter rules */
    631 int IPACM_Iface::init_fl_rule(ipa_ip_type iptype)
    632 {
    633 
    634 	int res = IPACM_SUCCESS, len = 0;
    635 	struct ipa_flt_rule_add flt_rule_entry;
    636 	ipa_ioc_add_flt_rule *m_pFilteringTable;
    637 
    638   /* Adding this hack because WLAN may not registered for Rx-endpoint, other ifaces will always have*/
    639 	const char *dev_wlan0="wlan0";
    640 	const char *dev_wlan1="wlan1";
    641 	const char *dev_ecm0="ecm0";
    642 
    643     /* ADD corresponding ipa_rm_resource_name of RX-endpoint before adding all IPV4V6 FT-rules */
    644 	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))
    645 	{
    646 		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);
    647 	}
    648 	else
    649 	{
    650 		if(rx_prop != NULL)
    651 		{
    652 			IPACMDBG_H("dev %s add producer dependency\n", dev_name);
    653 			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]);
    654 			IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe],false);
    655 		}
    656 		else
    657 		{
    658 			/* only wlan may take software-path, not register Rx-property*/
    659 			if(strcmp(dev_name,dev_wlan0) == 0 || strcmp(dev_name,dev_wlan1) == 0)
    660 			{
    661 				IPACMDBG_H("dev %s add producer dependency\n", dev_name);
    662 				IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_HSIC_PROD);
    663 				IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_HSIC_PROD,true);
    664 			}
    665 			if(strcmp(dev_name,dev_ecm0) == 0)
    666 			{
    667 				IPACMDBG_H("dev %s add producer dependency\n", dev_name);
    668 				IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_USB_PROD);
    669 				IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_USB_PROD,true);
    670 			}
    671 		}
    672 	}
    673 	if (rx_prop == NULL)
    674 	{
    675 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
    676 		return IPACM_SUCCESS;
    677 	}
    678 
    679 	/* construct ipa_ioc_add_flt_rule with default filter rules */
    680 	if (iptype == IPA_IP_v4)
    681 	{
    682 		len = sizeof(struct ipa_ioc_add_flt_rule) +
    683 			 (IPV4_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add));
    684 
    685 		m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
    686 		if (!m_pFilteringTable)
    687 		{
    688 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
    689 			return IPACM_FAILURE;
    690 		}
    691 
    692 		m_pFilteringTable->commit = 1;
    693 		m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
    694 		m_pFilteringTable->global = false;
    695 		m_pFilteringTable->ip = iptype;
    696 		m_pFilteringTable->num_rules = (uint8_t)IPV4_DEFAULT_FILTERTING_RULES;
    697 
    698 		/* Configuring Fragment Filtering Rule */
    699 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
    700 
    701 		flt_rule_entry.rule.retain_hdr = 1;
    702 		flt_rule_entry.at_rear = true;
    703 		flt_rule_entry.flt_rule_hdl = -1;
    704 		flt_rule_entry.status = -1;
    705 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
    706 #ifdef FEATURE_IPA_V3
    707 		flt_rule_entry.at_rear = false;
    708 		flt_rule_entry.rule.hashable = false;
    709 #endif
    710 		IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
    711 		memcpy(&flt_rule_entry.rule.attrib,
    712 					 &rx_prop->rx[0].attrib,
    713 					 sizeof(flt_rule_entry.rule.attrib));
    714 
    715 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
    716 		memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
    717 
    718 		/* Configuring Multicast Filtering Rule */
    719 		memcpy(&flt_rule_entry.rule.attrib,
    720 					 &rx_prop->rx[0].attrib,
    721 					 sizeof(flt_rule_entry.rule.attrib));
    722 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
    723 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xF0000000;
    724 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000;
    725 #ifdef FEATURE_IPA_V3
    726 		flt_rule_entry.at_rear = true;
    727 		flt_rule_entry.rule.hashable = true;
    728 #endif
    729 		memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
    730 
    731 		/* Configuring Broadcast Filtering Rule */
    732 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
    733 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF;
    734 #ifdef FEATURE_IPA_V3
    735 		flt_rule_entry.at_rear = true;
    736 		flt_rule_entry.rule.hashable = true;
    737 #endif
    738 		memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
    739 
    740 		if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
    741 		{
    742 			IPACMERR("Error Adding Filtering rule, aborting...\n");
    743 			res = IPACM_FAILURE;
    744 			goto fail;
    745 		}
    746 		else
    747 		{
    748 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES);
    749 			/* copy filter hdls */
    750 			for (int i = 0; i < IPV4_DEFAULT_FILTERTING_RULES; i++)
    751 			{
    752 				if (m_pFilteringTable->rules[i].status == 0)
    753 				{
    754 					dft_v4fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl;
    755 					IPACMDBG_H("Default v4 filter Rule %d HDL:0x%x\n", i, dft_v4fl_rule_hdl[i]);
    756 				}
    757 				else
    758 				{
    759 					IPACMERR("Failed adding default v4 Filtering rule %d\n", i);
    760 				}
    761 			}
    762 		}
    763 	}
    764 	else
    765 	{
    766 		len = sizeof(struct ipa_ioc_add_flt_rule) +
    767 			 (IPV6_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add));
    768 
    769 		m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
    770 		if (!m_pFilteringTable)
    771 		{
    772 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
    773 			return IPACM_FAILURE;
    774 		}
    775 
    776 		m_pFilteringTable->commit = 1;
    777 		m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
    778 		m_pFilteringTable->global = false;
    779 		m_pFilteringTable->ip = iptype;
    780 		m_pFilteringTable->num_rules = (uint8_t)IPV6_DEFAULT_FILTERTING_RULES;
    781 
    782 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
    783 
    784 		flt_rule_entry.rule.retain_hdr = 1;
    785 		flt_rule_entry.at_rear = true;
    786 		flt_rule_entry.flt_rule_hdl = -1;
    787 		flt_rule_entry.status = -1;
    788 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
    789 		/* Configuring Multicast Filtering Rule */
    790 		memcpy(&flt_rule_entry.rule.attrib,
    791 					 &rx_prop->rx[0].attrib,
    792 					 sizeof(flt_rule_entry.rule.attrib));
    793 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
    794 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
    795 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
    796 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
    797 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
    798 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF000000;
    799 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
    800 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
    801 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
    802 #ifdef FEATURE_IPA_V3
    803 		flt_rule_entry.at_rear = true;
    804 		flt_rule_entry.rule.hashable = true;
    805 #endif
    806 		memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
    807 
    808 		/* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */
    809 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
    810 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
    811 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
    812 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
    813 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFE800000;
    814 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
    815 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
    816 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
    817 #ifdef FEATURE_IPA_V3
    818 		flt_rule_entry.at_rear = true;
    819 		flt_rule_entry.rule.hashable = true;
    820 #endif
    821 		memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
    822 
    823 		/* Configuring fec0::/10 Reserved by IETF Filtering Rule */
    824 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
    825 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
    826 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
    827 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
    828 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFEC00000;
    829 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
    830 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
    831 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
    832 #ifdef FEATURE_IPA_V3
    833 		flt_rule_entry.at_rear = true;
    834 		flt_rule_entry.rule.hashable = true;
    835 #endif
    836 		memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
    837 
    838 #ifdef FEATURE_IPA_ANDROID
    839 		IPACMDBG_H("Add TCP ctrl rules: total num %d\n", IPV6_DEFAULT_FILTERTING_RULES);
    840 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
    841 
    842 		flt_rule_entry.at_rear = true;
    843 		flt_rule_entry.flt_rule_hdl = -1;
    844 		flt_rule_entry.status = -1;
    845 
    846 		flt_rule_entry.rule.retain_hdr = 1;
    847 		flt_rule_entry.rule.to_uc = 0;
    848 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
    849 		flt_rule_entry.rule.eq_attrib_type = 1;
    850 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap = 0;
    851 
    852 		if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA)
    853 		{
    854 #ifdef FEATURE_IPA_V3
    855 			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<9);
    856 #else
    857 			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<14);
    858 #endif
    859 			flt_rule_entry.rule.eq_attrib.metadata_meq32_present = 1;
    860 			flt_rule_entry.rule.eq_attrib.metadata_meq32.offset = 0;
    861 			flt_rule_entry.rule.eq_attrib.metadata_meq32.value = rx_prop->rx[0].attrib.meta_data;
    862 			flt_rule_entry.rule.eq_attrib.metadata_meq32.mask = rx_prop->rx[0].attrib.meta_data_mask;
    863 		}
    864 
    865 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<1);
    866 		flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1;
    867 		flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP;
    868 
    869 #ifdef FEATURE_IPA_V3
    870 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7);
    871 #else
    872 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8);
    873 #endif
    874 		flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1;
    875 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12;
    876 
    877 		/* add TCP FIN rule*/
    878 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_FIN_SHIFT);
    879 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_FIN_SHIFT);
    880 		memcpy(&(m_pFilteringTable->rules[3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
    881 
    882 		/* add TCP SYN rule*/
    883 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_SYN_SHIFT);
    884 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_SYN_SHIFT);
    885 		memcpy(&(m_pFilteringTable->rules[4]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
    886 
    887 		/* add TCP RST rule*/
    888 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_RST_SHIFT);
    889 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_RST_SHIFT);
    890 		memcpy(&(m_pFilteringTable->rules[5]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
    891 #endif
    892 		if (m_filtering.AddFilteringRule(m_pFilteringTable) == false)
    893 		{
    894 			IPACMERR("Error Adding Filtering rule, aborting...\n");
    895 			res = IPACM_FAILURE;
    896 			goto fail;
    897 		}
    898 		else
    899 		{
    900 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES);
    901 			/* copy filter hdls */
    902 			for (int i = 0;
    903 					 i < IPV6_DEFAULT_FILTERTING_RULES;
    904 					 i++)
    905 			{
    906 				if (m_pFilteringTable->rules[i].status == 0)
    907 				{
    908 					dft_v6fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl;
    909 					IPACMDBG_H("Default v6 Filter Rule %d HDL:0x%x\n", i, dft_v6fl_rule_hdl[i]);
    910 				}
    911 				else
    912 				{
    913 					IPACMERR("Failing adding v6 default IPV6 rule %d\n", i);
    914 				}
    915 			}
    916 		}
    917 	}
    918 
    919 
    920 fail:
    921 	free(m_pFilteringTable);
    922 
    923 	return res;
    924 }
    925 
    926 /*  get ipa interface name */
    927 int IPACM_Iface::ipa_get_if_index
    928 (
    929   char * if_name,
    930   int * if_index
    931 )
    932 {
    933 	int fd;
    934 	struct ifreq ifr;
    935 
    936 	if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    937 	{
    938 		IPACMERR("get interface index socket create failed \n");
    939 		return IPACM_FAILURE;
    940 	}
    941 
    942 	if(strlen(if_name) >= sizeof(ifr.ifr_name))
    943 	{
    944 		IPACMERR("interface name overflows: len %zu\n", strlen(if_name));
    945 		close(fd);
    946 		return IPACM_FAILURE;
    947 	}
    948 
    949 	memset(&ifr, 0, sizeof(struct ifreq));
    950 	(void)strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
    951 	IPACMDBG_H("interface name (%s)\n", if_name);
    952 
    953 	if(ioctl(fd,SIOCGIFINDEX , &ifr) < 0)
    954 	{
    955 		IPACMERR("call_ioctl_on_dev: ioctl failed, interface name (%s):\n", ifr.ifr_name);
    956 		close(fd);
    957 		return IPACM_FAILURE;
    958 	}
    959 
    960 	*if_index = ifr.ifr_ifindex;
    961 	IPACMDBG_H("Interface index %d\n", *if_index);
    962 	close(fd);
    963 	return IPACM_SUCCESS;
    964 }
    965 
    966 void IPACM_Iface::config_ip_type(ipa_ip_type iptype)
    967 {
    968 	/* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/
    969 	if (iptype == IPA_IP_v4)
    970 	{
    971 		if ((ip_type == IPA_IP_v4) || (ip_type == IPA_IP_MAX))
    972 		{
    973 			IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
    974 			return;
    975 		}
    976 
    977 		if (ip_type == IPA_IP_v6)
    978 		{
    979 			ip_type = IPA_IP_MAX;
    980 		}
    981 		else
    982 		{
    983 			ip_type = IPA_IP_v4;
    984 		}
    985 		IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
    986 	}
    987 	else
    988 	{
    989 		if ((ip_type == IPA_IP_v6) || (ip_type == IPA_IP_MAX))
    990 		{
    991 			IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
    992 			return;
    993 		}
    994 
    995 		if (ip_type == IPA_IP_v4)
    996 		{
    997 			ip_type = IPA_IP_MAX;
    998 		}
    999 		else
   1000 		{
   1001 			ip_type = IPA_IP_v6;
   1002 		}
   1003 
   1004 		IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
   1005 	}
   1006 
   1007 	return;
   1008 }
   1009