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