| /* |
| Copyright (c) 2013, The Linux Foundation. All rights reserved. |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions are |
| met: |
| * Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| |
| * Redistributions in binary form must reproduce the above |
| copyright notice, this list of conditions and the following |
| disclaimer in the documentation and/or other materials provided |
| with the distribution. |
| |
| * Neither the name of The Linux Foundation nor the names of its |
| contributors may be used to endorse or promote products derived |
| from this software without specific prior written permission. |
| |
| THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| /*! |
| @file |
| IPACM_Lan.cpp |
| |
| @brief |
| This file implements the LAN iface functionality. |
| |
| @Author |
| Skylar Chang |
| |
| */ |
| #include <string.h> |
| #include <fcntl.h> |
| #include <sys/ioctl.h> |
| #include <IPACM_Netlink.h> |
| #include <IPACM_Lan.h> |
| #include <IPACM_Wan.h> |
| #include <IPACM_IfaceManager.h> |
| #include "linux/rmnet_ipa_fd_ioctl.h" |
| #include "linux/ipa_qmi_service_v01.h" |
| #include "linux/msm_ipa.h" |
| |
| IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index) |
| { |
| num_uni_rt = 0; |
| ipv6_set = 0; |
| rt_rule_len = sizeof(struct ipa_lan_rt_rule) + (iface_query->num_tx_props * sizeof(uint32_t)); |
| route_rule = (struct ipa_lan_rt_rule *)calloc(IPA_MAX_NUM_UNICAST_ROUTE_RULES, rt_rule_len); |
| if (route_rule == NULL) |
| { |
| IPACMERR("unable to allocate memory\n"); |
| return; |
| } |
| |
| IPACMDBG(" IPACM->IPACM_Lan(%d) constructor: Tx:%d Rx:%d\n", ipa_if_num, |
| iface_query->num_tx_props, iface_query->num_rx_props); |
| |
| num_wan_ul_fl_rule_v4 = 0; |
| num_wan_ul_fl_rule_v6 = 0; |
| |
| memset(wan_ul_fl_rule_hdl_v4, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t)); |
| memset(wan_ul_fl_rule_hdl_v6, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t)); |
| |
| return; |
| } |
| |
| IPACM_Lan::~IPACM_Lan() |
| { |
| IPACM_EvtDispatcher::deregistr(this); |
| IPACM_IfaceManager::deregistr(this); |
| return; |
| } |
| |
| |
| /* LAN-iface's callback function */ |
| void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) |
| { |
| int ipa_interface_index; |
| ipacm_ext_prop* ext_prop; |
| |
| switch (event) |
| { |
| case IPA_LINK_DOWN_EVENT: |
| { |
| ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; |
| ipa_interface_index = iface_ipa_index_query(data->if_index); |
| if (ipa_interface_index == ipa_if_num) |
| { |
| IPACMDBG("Received IPA_LINK_DOWN_EVENT\n"); |
| handle_down_evt(); |
| IPACMDBG("ipa_LAN (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num); |
| IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface |
| delete this; |
| return; |
| } |
| } |
| break; |
| |
| case IPA_ADDR_ADD_EVENT: |
| { |
| ipacm_event_data_addr *data = (ipacm_event_data_addr *)param; |
| ipa_interface_index = iface_ipa_index_query(data->if_index); |
| |
| if ( (data->iptype == IPA_IP_v4 && data->ipv4_addr == 0) || |
| (data->iptype == IPA_IP_v6 && |
| data->ipv6_addr[0] == 0 && data->ipv6_addr[1] == 0 && |
| data->ipv6_addr[2] == 0 && data->ipv6_addr[3] == 0) ) |
| { |
| IPACMDBG("Invalid address, ignore IPA_ADDR_ADD_EVENT event\n"); |
| return; |
| } |
| |
| |
| if (ipa_interface_index == ipa_if_num) |
| { |
| IPACMDBG("Received IPA_ADDR_ADD_EVENT\n"); |
| |
| /* check v4 not setup before, v6 can have 2 iface ip */ |
| if( ((data->iptype != ip_type) && (ip_type != IPA_IP_MAX)) |
| || ((data->iptype==IPA_IP_v6) && (num_dft_rt_v6!=MAX_DEFAULT_v6_ROUTE_RULES))) |
| { |
| IPACMDBG("Got IPA_ADDR_ADD_EVENT ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6); |
| handle_addr_evt(data); |
| handle_private_subnet(data->iptype); |
| |
| if (IPACM_Wan::isWanUP()) |
| { |
| if(IPACM_Wan::backhaul_is_sta_mode == false) |
| { |
| if(data->iptype == IPA_IP_v4 || data->iptype == IPA_IP_MAX) |
| { |
| ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); |
| handle_wan_up_ex(ext_prop, IPA_IP_v4); |
| } |
| } |
| else |
| { |
| handle_wan_up(IPA_IP_v4); |
| } |
| } |
| |
| if(IPACM_Wan::isWanUP_V6()) |
| { |
| if(IPACM_Wan::backhaul_is_sta_mode == false) |
| { |
| if(data->iptype == IPA_IP_v6 || data->iptype == IPA_IP_MAX) |
| { |
| ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); |
| handle_wan_up_ex(ext_prop, IPA_IP_v6); |
| } |
| } |
| else |
| { |
| handle_wan_up(IPA_IP_v6); |
| } |
| } |
| |
| /* Post event to NAT */ |
| if (data->iptype == IPA_IP_v4) |
| { |
| ipacm_cmd_q_data evt_data; |
| ipacm_event_iface_up *info; |
| |
| info = (ipacm_event_iface_up *) |
| malloc(sizeof(ipacm_event_iface_up)); |
| if (info == NULL) |
| { |
| IPACMERR("Unable to allocate memory\n"); |
| return; |
| } |
| |
| memcpy(info->ifname, dev_name, IF_NAME_LEN); |
| info->ipv4_addr = data->ipv4_addr; |
| info->addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[0].subnet_mask; |
| |
| evt_data.event = IPA_HANDLE_LAN_UP; |
| evt_data.evt_data = (void *)info; |
| |
| /* Insert IPA_HANDLE_LAN_UP to command queue */ |
| IPACMDBG("posting IPA_HANDLE_LAN_UP for IPv4 with below information\n"); |
| IPACMDBG("IPv4 address:0x%x, IPv4 address mask:0x%x\n", |
| info->ipv4_addr, info->addr_mask); |
| IPACM_EvtDispatcher::PostEvt(&evt_data); |
| } |
| } |
| } |
| } |
| break; |
| |
| case IPA_HANDLE_WAN_UP: |
| IPACMDBG("Received IPA_HANDLE_WAN_UP event\n"); |
| |
| if(IPACM_Wan::backhaul_is_sta_mode == false) |
| { |
| if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) |
| { |
| ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); |
| handle_wan_up_ex(ext_prop, IPA_IP_v4); |
| } |
| } |
| else |
| { |
| handle_wan_up(IPA_IP_v4); |
| } |
| break; |
| |
| case IPA_HANDLE_WAN_UP_V6: |
| IPACMDBG("Received IPA_HANDLE_WAN_UP_V6 event\n"); |
| |
| if(IPACM_Wan::backhaul_is_sta_mode == false) |
| { |
| if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) |
| { |
| ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); |
| handle_wan_up_ex(ext_prop, IPA_IP_v6); |
| } |
| } |
| else |
| { |
| handle_wan_up(IPA_IP_v6); |
| } |
| break; |
| |
| case IPA_ROUTE_ADD_EVENT: |
| { |
| ipacm_event_data_addr *data = (ipacm_event_data_addr *)param; |
| ipa_interface_index = iface_ipa_index_query(data->if_index); |
| |
| /* unicast routing rule add */ |
| if (ipa_interface_index == ipa_if_num) |
| { |
| IPACMDBG("Received IPA_ROUTE_ADD_EVENT\n"); |
| handle_route_add_evt(data); |
| } |
| } |
| break; |
| |
| case IPA_HANDLE_WAN_DOWN: |
| IPACMDBG("Received IPA_HANDLE_WAN_DOWN event\n"); |
| handle_wan_down(IPACM_Wan::backhaul_is_sta_mode); |
| break; |
| |
| case IPA_HANDLE_WAN_DOWN_V6: |
| IPACMDBG("Received IPA_HANDLE_WAN_DOWN event\n"); |
| handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode); |
| break; |
| |
| case IPA_ROUTE_DEL_EVENT: |
| { |
| ipacm_event_data_addr *data = (ipacm_event_data_addr *)param; |
| ipa_interface_index = iface_ipa_index_query(data->if_index); |
| |
| /* unicast routing rule del */ |
| if (ipa_interface_index == ipa_if_num) |
| { |
| IPACMDBG("Received IPA_ROUTE_DEL_EVENT\n"); |
| handle_route_del_evt(data); |
| } |
| } |
| break; |
| |
| case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT: |
| { |
| ipacm_event_data_all *data = (ipacm_event_data_all *)param; |
| ipa_interface_index = iface_ipa_index_query(data->if_index); |
| if ((ipa_interface_index == ipa_if_num) && (data->iptype == IPA_IP_v6)) |
| { |
| IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT for ipv6\n"); |
| handle_route_add_evt_v6(data); |
| } |
| /* support ipv4 unicast route add coming from bridge0 via new_neighbor event */ |
| if ((ipa_interface_index == ipa_if_num) && (data->iptype == IPA_IP_v4)) |
| { |
| IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT for ipv4 \n"); |
| ipacm_event_data_addr *data2; |
| data2 = (ipacm_event_data_addr *) |
| malloc(sizeof(ipacm_event_data_addr)); |
| if (data2 == NULL) |
| { |
| IPACMERR("Unable to allocate memory\n"); |
| return; |
| } |
| memset(data2, 0, sizeof(data2)); |
| data2->iptype = IPA_IP_v4; |
| data2->ipv4_addr = data->ipv4_addr; |
| data2->ipv4_addr_mask = 0xFFFFFFFF; |
| IPACMDBG("IPv4 address:0x%x, mask:0x%x\n", |
| data2->iptype, data2->ipv4_addr_mask); |
| handle_route_add_evt(data2); |
| free(data2); |
| } |
| } |
| break; |
| |
| case IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT: |
| { |
| ipacm_event_data_all *data = (ipacm_event_data_all *)param; |
| ipa_interface_index = iface_ipa_index_query(data->if_index); |
| if ((ipa_interface_index == ipa_if_num) && (data->iptype == IPA_IP_v6) ) |
| { |
| IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT for ipv6\n"); |
| handle_route_del_evt_v6(data); |
| } |
| /* support ipv4 unicast route delete coming from bridge0 via new_neighbor event */ |
| if ((ipa_interface_index == ipa_if_num) && (data->iptype == IPA_IP_v4)) |
| { |
| IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT for ipv4 \n"); |
| ipacm_event_data_addr *data2; |
| data2 = (ipacm_event_data_addr *) |
| malloc(sizeof(ipacm_event_data_addr)); |
| if (data2 == NULL) |
| { |
| IPACMERR("Unable to allocate memory\n"); |
| return; |
| } |
| memset(data2, 0, sizeof(data2)); |
| data2->iptype = IPA_IP_v4; |
| data2->ipv4_addr = data->ipv4_addr; |
| data2->ipv4_addr_mask = 0xFFFFFFFF; |
| IPACMDBG("IPv4 address:0x%x, mask:0x%x\n", |
| data2->iptype, data2->ipv4_addr_mask); |
| handle_route_add_evt(data2); |
| free(data2); |
| } |
| } |
| break; |
| |
| case IPA_SW_ROUTING_ENABLE: |
| IPACMDBG("Received IPA_SW_ROUTING_ENABLE\n"); |
| /* handle software routing enable event*/ |
| handle_software_routing_enable(); |
| break; |
| |
| case IPA_SW_ROUTING_DISABLE: |
| IPACMDBG("Received IPA_SW_ROUTING_DISABLE\n"); |
| /* handle software routing disable event*/ |
| handle_software_routing_disable(); |
| break; |
| |
| default: |
| break; |
| } |
| |
| return; |
| } |
| |
| |
| /*handle USB client IPv6*/ |
| int IPACM_Lan::handle_route_add_evt_v6(ipacm_event_data_all *data) |
| { |
| /* add unicate route for LAN */ |
| struct ipa_ioc_add_rt_rule *rt_rule; |
| struct ipa_rt_rule_add *rt_rule_entry; |
| struct ipa_ioc_get_hdr sRetHeader; |
| uint32_t tx_index; |
| int v6_num; |
| |
| IPACMDBG(" usb MAC %02x:%02x:%02x:%02x:%02x:%02x\n", |
| data->mac_addr[0], |
| data->mac_addr[1], |
| data->mac_addr[2], |
| data->mac_addr[3], |
| data->mac_addr[4], |
| data->mac_addr[5]); |
| |
| if (tx_prop == NULL) |
| { |
| IPACMDBG("No Tx properties registered for iface %s\n", dev_name); |
| return IPACM_SUCCESS; |
| } |
| |
| IPACMDBG("Ip-type received %d, ipv6_set: %d\n", data->iptype,ipv6_set); |
| if (data->iptype == IPA_IP_v6) |
| { |
| /* check if all 0 not valid ipv6 address */ |
| if ((data->ipv6_addr[0]!= 0) || (data->ipv6_addr[1]!= 0) || |
| (data->ipv6_addr[2]!= 0) || (data->ipv6_addr[3] || 0)) |
| { |
| IPACMDBG("ipv6 address: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); |
| if(ipv6_set<IPV6_NUM_ADDR) |
| { |
| /* check if see that before or not*/ |
| for(v6_num = 0;v6_num < ipv6_set;v6_num++) |
| { |
| if( data->ipv6_addr[0] == v6_addr[v6_num][0] && |
| data->ipv6_addr[1] == v6_addr[v6_num][1] && |
| data->ipv6_addr[2]== v6_addr[v6_num][2] && |
| data->ipv6_addr[3] == v6_addr[v6_num][3]) |
| { |
| IPACMDBG("Already see this ipv6 addr for LAN iface \n"); |
| return IPACM_SUCCESS; /* not setup the RT rules*/ |
| break; |
| } |
| } |
| |
| /* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */ |
| IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false); |
| |
| /* not see this ipv6 before for LAN client*/ |
| v6_addr[ipv6_set][0] = data->ipv6_addr[0]; |
| v6_addr[ipv6_set][1] = data->ipv6_addr[1]; |
| v6_addr[ipv6_set][2] = data->ipv6_addr[2]; |
| v6_addr[ipv6_set][3] = data->ipv6_addr[3]; |
| |
| /* unicast RT rule add start */ |
| rt_rule = (struct ipa_ioc_add_rt_rule *) |
| calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + |
| 1 * sizeof(struct ipa_rt_rule_add)); |
| if (!rt_rule) |
| { |
| IPACMERR("fail\n"); |
| return IPACM_FAILURE; |
| } |
| |
| rt_rule->commit = 1; |
| rt_rule->num_rules = (uint8_t)1; |
| rt_rule->ip = data->iptype; |
| rt_rule_entry = &rt_rule->rules[0]; |
| rt_rule_entry->at_rear = false; |
| |
| |
| for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) |
| { |
| |
| if(data->iptype != tx_prop->tx[tx_index].ip) |
| { |
| IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d no unicast LAN RT-rule added\n", |
| tx_index, tx_prop->tx[tx_index].ip,data->iptype); |
| continue; |
| } |
| |
| strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name); |
| |
| /* Support QCMAP LAN traffic feature, send to A5 */ |
| rt_rule_entry->rule.dst = iface_query->excp_pipe; |
| memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib)); |
| rt_rule_entry->rule.hdr_hdl = 0; |
| rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0]; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1]; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2]; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = data->ipv6_addr[3]; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; |
| |
| if (false == m_routing.AddRoutingRule(rt_rule)) |
| { |
| IPACMERR("Routing rule addition failed!\n"); |
| free(rt_rule); |
| return IPACM_FAILURE; |
| } |
| get_rt_ruleptr(route_rule, num_uni_rt)->rt_rule_hdl[tx_index] |
| = rt_rule_entry->rt_rule_hdl; |
| IPACMDBG("ipv6 rt rule hdl1 for LAN-table=0x%x, entry:0x%x\n", rt_rule_entry->rt_rule_hdl,get_rt_ruleptr(route_rule, num_uni_rt)->rt_rule_hdl[tx_index]); |
| |
| /* Construct same v6 rule for rt_tbl_wan_v6 */ |
| if (tx_prop->tx[tx_index].hdr_name) |
| { |
| memset(&sRetHeader, 0, sizeof(sRetHeader)); |
| strncpy(sRetHeader.name, |
| tx_prop->tx[tx_index].hdr_name, |
| sizeof(tx_prop->tx[tx_index].hdr_name)); |
| |
| if (false == m_header.GetHeaderHandle(&sRetHeader)) |
| { |
| IPACMERR(" ioctl failed\n"); |
| free(rt_rule); |
| return IPACM_FAILURE; |
| } |
| |
| rt_rule_entry->rule.hdr_hdl = sRetHeader.hdl; |
| } |
| |
| /* Downlink traffic from Wan iface, directly through IPA */ |
| rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; |
| memcpy(&rt_rule_entry->rule.attrib, |
| &tx_prop->tx[tx_index].attrib, |
| sizeof(rt_rule_entry->rule.attrib)); |
| rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0]; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1]; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2]; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = data->ipv6_addr[3]; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; |
| |
| strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name); |
| if (false == m_routing.AddRoutingRule(rt_rule)) |
| { |
| IPACMERR("Routing rule addition failed!\n"); |
| free(rt_rule); |
| return IPACM_FAILURE; |
| } |
| get_rt_ruleptr(route_rule, (num_uni_rt+1))->rt_rule_hdl[tx_index] |
| = rt_rule_entry->rt_rule_hdl; |
| IPACMDBG("ipv6 rt rule hdl1 for WAN-table=0x%x, entry:0x%x\n", rt_rule_entry->rt_rule_hdl,get_rt_ruleptr(route_rule, (num_uni_rt+1))->rt_rule_hdl[tx_index]); |
| |
| } |
| |
| get_rt_ruleptr(route_rule, num_uni_rt)->ip = IPA_IP_v6; |
| get_rt_ruleptr(route_rule, num_uni_rt)->v6_addr[0] = data->ipv6_addr[0]; |
| get_rt_ruleptr(route_rule, num_uni_rt)->v6_addr[1] = data->ipv6_addr[1]; |
| get_rt_ruleptr(route_rule, num_uni_rt)->v6_addr[2] = data->ipv6_addr[2]; |
| get_rt_ruleptr(route_rule, num_uni_rt)->v6_addr[3] = data->ipv6_addr[3]; |
| |
| get_rt_ruleptr(route_rule, (num_uni_rt+1))->ip = IPA_IP_v6; |
| get_rt_ruleptr(route_rule, (num_uni_rt+1))->v6_addr[0] = data->ipv6_addr[0]; |
| get_rt_ruleptr(route_rule, (num_uni_rt+1))->v6_addr[1] = data->ipv6_addr[1]; |
| get_rt_ruleptr(route_rule, (num_uni_rt+1))->v6_addr[2] = data->ipv6_addr[2]; |
| get_rt_ruleptr(route_rule, (num_uni_rt+1))->v6_addr[3] = data->ipv6_addr[3]; |
| |
| num_uni_rt=num_uni_rt+2; |
| free(rt_rule); |
| ipv6_set++; |
| IPACMDBG("Total unicast Rt rules: %d\n", num_uni_rt); |
| } |
| else |
| { |
| IPACMDBG("Already got 3 ipv6 addr for LAN usb-client:\n"); |
| return IPACM_SUCCESS; /* not setup the RT rules*/ |
| } |
| } |
| } |
| |
| return IPACM_SUCCESS; |
| } |
| |
| |
| /* handle unicast routing rule add event */ |
| int IPACM_Lan::handle_route_add_evt(ipacm_event_data_addr *data) |
| { |
| /* add unicate route for LAN */ |
| struct ipa_ioc_add_rt_rule *rt_rule; |
| struct ipa_rt_rule_add *rt_rule_entry; |
| struct ipa_ioc_get_hdr sRetHeader; |
| uint32_t tx_index; |
| int i; |
| |
| IPACMDBG("LAN callback: unicast IPA_ROUTE_ADD_EVENT\n"); |
| |
| if (tx_prop == NULL) |
| { |
| IPACMDBG("No Tx properties registered for iface %s\n", dev_name); |
| return IPACM_SUCCESS; |
| } |
| |
| if (data->iptype == IPA_IP_v6) |
| { |
| IPACMDBG("Not setup v6 unicast RT-rule with new_route event for iface %s\n", dev_name); |
| return IPACM_SUCCESS; |
| } |
| |
| |
| if (num_uni_rt < IPA_MAX_NUM_UNICAST_ROUTE_RULES) |
| { |
| /* check the unicast RT rule is set or not*/ |
| for (i = 0; i < num_uni_rt; i++) |
| { |
| |
| if ( data->iptype == IPA_IP_v4 && |
| (data->ipv4_addr == get_rt_ruleptr(route_rule, i)->v4_addr) && |
| (data->ipv4_addr_mask == get_rt_ruleptr(route_rule, i)->v4_addr_mask) ) |
| { |
| IPACMDBG("find previous-added ipv4 unicast RT entry as index: %d, ignore adding\n",i); |
| return IPACM_SUCCESS; |
| break; |
| } |
| } |
| |
| /* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV4 RT-rule set */ |
| IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false); |
| |
| /* unicast RT rule add start */ |
| rt_rule = (struct ipa_ioc_add_rt_rule *) |
| calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + |
| 1 * sizeof(struct ipa_rt_rule_add)); |
| if (!rt_rule) |
| { |
| IPACMERR("fail\n"); |
| return IPACM_FAILURE; |
| } |
| |
| rt_rule->commit = 1; |
| rt_rule->num_rules = (uint8_t)1; |
| rt_rule->ip = data->iptype; |
| |
| if (data->iptype == IPA_IP_v4) |
| { |
| strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name); |
| } |
| |
| rt_rule_entry = &rt_rule->rules[0]; |
| rt_rule_entry->at_rear = false; |
| |
| for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) |
| { |
| |
| if(data->iptype != tx_prop->tx[tx_index].ip) |
| { |
| IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d no unicast LAN RT-rule added\n", |
| tx_index, tx_prop->tx[tx_index].ip,data->iptype); |
| continue; |
| } |
| |
| if (tx_prop->tx[tx_index].hdr_name) |
| { |
| memset(&sRetHeader, 0, sizeof(sRetHeader)); |
| strncpy(sRetHeader.name, |
| tx_prop->tx[tx_index].hdr_name, |
| sizeof(tx_prop->tx[tx_index].hdr_name)); |
| |
| if (false == m_header.GetHeaderHandle(&sRetHeader)) |
| { |
| IPACMERR(" ioctl failed\n"); |
| free(rt_rule); |
| return IPACM_FAILURE; |
| } |
| |
| rt_rule_entry->rule.hdr_hdl = sRetHeader.hdl; |
| } |
| rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; |
| memcpy(&rt_rule_entry->rule.attrib, |
| &tx_prop->tx[tx_index].attrib, |
| sizeof(rt_rule_entry->rule.attrib)); |
| rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; |
| if (data->iptype == IPA_IP_v4) |
| { |
| rt_rule_entry->rule.attrib.u.v4.dst_addr = data->ipv4_addr; |
| rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = data->ipv4_addr_mask; |
| } |
| |
| if (false == m_routing.AddRoutingRule(rt_rule)) |
| { |
| IPACMERR("Routing rule addition failed!\n"); |
| free(rt_rule); |
| return IPACM_FAILURE; |
| } |
| |
| IPACMDBG("rt rule hdl1=0x%x\n", rt_rule_entry->rt_rule_hdl); |
| get_rt_ruleptr(route_rule, num_uni_rt)->rt_rule_hdl[tx_index] |
| = rt_rule_entry->rt_rule_hdl; |
| } |
| |
| get_rt_ruleptr(route_rule, num_uni_rt)->ip = IPA_IP_v4; |
| get_rt_ruleptr(route_rule, num_uni_rt)->v4_addr = data->ipv4_addr; |
| get_rt_ruleptr(route_rule, num_uni_rt)->v4_addr_mask = data->ipv4_addr_mask; |
| IPACMDBG("index: %d, ip-family: %d, IPv4 address:0x%x, IPv4 address mask:0x%x \n", |
| num_uni_rt, get_rt_ruleptr(route_rule, num_uni_rt)->ip, |
| get_rt_ruleptr(route_rule, num_uni_rt)->v4_addr, |
| get_rt_ruleptr(route_rule, num_uni_rt)->v4_addr_mask); |
| |
| |
| free(rt_rule); |
| num_uni_rt++; |
| } |
| else |
| { |
| IPACMDBG("unicast rule oversize\n"); |
| return IPACM_FAILURE; |
| } |
| |
| return IPACM_SUCCESS; |
| } |
| |
| /* handle unicast routing rule del event */ |
| int IPACM_Lan::handle_route_del_evt(ipacm_event_data_addr *data) |
| { |
| int i; |
| uint32_t tx_index; |
| |
| if (tx_prop == NULL) |
| { |
| IPACMDBG("No Tx properties registered for iface %s\n", dev_name); |
| return IPACM_SUCCESS; |
| } |
| |
| if (data->iptype == IPA_IP_v6) |
| { |
| IPACMDBG("Not setup v6 unicast RT-rule with new_route event for iface %s\n", dev_name); |
| return IPACM_SUCCESS; |
| } |
| |
| /* delete 1 unicast RT rule */ |
| for (i = 0; i < num_uni_rt; i++) |
| { |
| |
| if (data->iptype == IPA_IP_v4) |
| { |
| if ((data->ipv4_addr == get_rt_ruleptr(route_rule, i)->v4_addr) && |
| (data->ipv4_addr_mask == get_rt_ruleptr(route_rule, i)->v4_addr_mask)) |
| { |
| for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) |
| { |
| if(data->iptype != tx_prop->tx[tx_index].ip) |
| { |
| IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d no unicast LAN RT-rule added\n", |
| tx_index, tx_prop->tx[tx_index].ip,data->iptype); |
| continue; |
| } |
| |
| if (m_routing.DeleteRoutingHdl(get_rt_ruleptr(route_rule, i)->rt_rule_hdl[tx_index], |
| IPA_IP_v4) == false) |
| { |
| IPACMERR("Routing rule deletion failed!\n"); |
| return IPACM_FAILURE; |
| } |
| } |
| |
| /* remove that delted route rule entry*/ |
| for (; i < num_uni_rt; i++) |
| { |
| get_rt_ruleptr(route_rule, i)->v4_addr = get_rt_ruleptr(route_rule, (i + 1))->v4_addr; |
| get_rt_ruleptr(route_rule, i)->v4_addr_mask = get_rt_ruleptr(route_rule, (i + 1))->v4_addr_mask; |
| get_rt_ruleptr(route_rule, i)->v6_addr[0] = get_rt_ruleptr(route_rule, (i + 1))->v6_addr[0]; |
| get_rt_ruleptr(route_rule, i)->v6_addr[1] = get_rt_ruleptr(route_rule, (i + 1))->v6_addr[1]; |
| get_rt_ruleptr(route_rule, i)->v6_addr[2] = get_rt_ruleptr(route_rule, (i + 1))->v6_addr[2]; |
| get_rt_ruleptr(route_rule, i)->v6_addr[3] = get_rt_ruleptr(route_rule, (i + 1))->v6_addr[3]; |
| get_rt_ruleptr(route_rule, i)->ip = get_rt_ruleptr(route_rule, (i + 1))->ip; |
| |
| for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) |
| { |
| get_rt_ruleptr(route_rule, i)->rt_rule_hdl[tx_index] = get_rt_ruleptr(route_rule, (i + 1))->rt_rule_hdl[tx_index]; |
| } |
| } |
| |
| num_uni_rt -= 1; |
| |
| /* Del v4 RM dependency */ |
| if(num_uni_rt == 0) |
| { |
| /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete all IPV4V6 RT-rule*/ |
| IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); |
| } |
| |
| return IPACM_SUCCESS; |
| } |
| } |
| |
| } |
| |
| return IPACM_FAILURE; |
| } |
| |
| /* handle unicast routing rule del event */ |
| int IPACM_Lan::handle_route_del_evt_v6(ipacm_event_data_all *data) |
| { |
| int i,v6_num; |
| uint32_t tx_index; |
| |
| if (tx_prop == NULL) |
| { |
| IPACMDBG("No Tx properties registered for iface %s\n", dev_name); |
| return IPACM_SUCCESS; |
| } |
| |
| /* delete 1 unicast RT rule with 2 entries */ |
| for (i = 0; i < num_uni_rt; i++) |
| { |
| if (data->iptype == IPA_IP_v6) |
| { |
| if ((data->ipv6_addr[0] == get_rt_ruleptr(route_rule, i)->v6_addr[0]) && |
| (data->ipv6_addr[1] == get_rt_ruleptr(route_rule, i)->v6_addr[1]) && |
| (data->ipv6_addr[2] == get_rt_ruleptr(route_rule, i)->v6_addr[2]) && |
| (data->ipv6_addr[3] == get_rt_ruleptr(route_rule, i)->v6_addr[3])) |
| { |
| for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) |
| { |
| if(data->iptype != tx_prop->tx[tx_index].ip) |
| { |
| IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d no unicast LAN RT-rule added\n", |
| tx_index, tx_prop->tx[tx_index].ip,data->iptype); |
| continue; |
| } |
| |
| if (m_routing.DeleteRoutingHdl(get_rt_ruleptr(route_rule, i)->rt_rule_hdl[tx_index], |
| IPA_IP_v6) == false) |
| { |
| IPACMERR("Routing rule deletion failed!\n"); |
| return IPACM_FAILURE; |
| } |
| |
| /* also delete the v6 rules for rt_tbl_wan_v6*/ |
| if (m_routing.DeleteRoutingHdl(get_rt_ruleptr(route_rule, i+1)->rt_rule_hdl[tx_index], |
| IPA_IP_v6) == false) |
| { |
| IPACMERR("Routing rule deletion failed!\n"); |
| return IPACM_FAILURE; |
| } |
| } |
| |
| /* remove that delted route rule entry*/ |
| for (; i < num_uni_rt; i++) |
| { |
| for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) |
| { |
| get_rt_ruleptr(route_rule, i)->rt_rule_hdl[tx_index] = get_rt_ruleptr(route_rule, (i + 2))->rt_rule_hdl[tx_index]; |
| } |
| get_rt_ruleptr(route_rule, i)->v4_addr = get_rt_ruleptr(route_rule, (i + 2))->v4_addr; |
| get_rt_ruleptr(route_rule, i)->v4_addr_mask = get_rt_ruleptr(route_rule, (i + 2))->v4_addr_mask; |
| get_rt_ruleptr(route_rule, i)->v6_addr[0] = get_rt_ruleptr(route_rule, (i + 2))->v6_addr[0]; |
| get_rt_ruleptr(route_rule, i)->v6_addr[1] = get_rt_ruleptr(route_rule, (i + 2))->v6_addr[1]; |
| get_rt_ruleptr(route_rule, i)->v6_addr[2] = get_rt_ruleptr(route_rule, (i + 2))->v6_addr[2]; |
| get_rt_ruleptr(route_rule, i)->v6_addr[3] = get_rt_ruleptr(route_rule, (i + 2))->v6_addr[3]; |
| get_rt_ruleptr(route_rule, i)->ip = get_rt_ruleptr(route_rule, (i + 2))->ip; |
| |
| } |
| |
| num_uni_rt -= 2; |
| |
| /* remove this ipv6-address from LAN client*/ |
| for(v6_num = 0;v6_num < ipv6_set;v6_num++) |
| { |
| if( data->ipv6_addr[0] == v6_addr[v6_num][0] && |
| data->ipv6_addr[1] == v6_addr[v6_num][1] && |
| data->ipv6_addr[2]== v6_addr[v6_num][2] && |
| data->ipv6_addr[3] == v6_addr[v6_num][3]) |
| { |
| IPACMDBG("Delete this ipv6 addr for LAN iface \n"); |
| /* remove that delted route rule entry*/ |
| for (; v6_num <= ipv6_set; v6_num++) |
| { |
| v6_addr[v6_num][0] = v6_addr[v6_num+1][0]; |
| v6_addr[v6_num][1] = v6_addr[v6_num+1][1]; |
| v6_addr[v6_num][2] = v6_addr[v6_num+1][2]; |
| v6_addr[v6_num][3] = v6_addr[v6_num+1][3]; |
| } |
| ipv6_set-=1; |
| IPACMDBG("left %d ipv6-addr for LAN iface \n",ipv6_set); |
| break; |
| } |
| } |
| |
| /* Del v6 RM dependency */ |
| if(num_uni_rt == 0) |
| { |
| /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete all IPV4V6 RT-rule */ |
| IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); |
| } |
| return IPACM_SUCCESS; |
| } |
| } |
| } |
| return IPACM_FAILURE; |
| } |
| |
| /* delete filter rule for wan_down event for IPv4*/ |
| int IPACM_Lan::handle_wan_down(bool is_sta_mode) |
| { |
| ipa_fltr_installed_notif_req_msg_v01 flt_index; |
| int fd; |
| |
| fd = open(IPA_DEVICE_NAME, O_RDWR); |
| if (0 == fd) |
| { |
| IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); |
| return IPACM_FAILURE; |
| } |
| |
| if(is_sta_mode == false) |
| { |
| if (m_filtering.DeleteFilteringHdls(wan_ul_fl_rule_hdl_v4, |
| IPA_IP_v4, num_wan_ul_fl_rule_v4) == false) |
| { |
| IPACMERR("Error Deleting RuleTable(1) to Filtering, aborting...\n"); |
| close(fd); |
| return IPACM_FAILURE; |
| } |
| |
| memset(&flt_index, 0, sizeof(flt_index)); |
| flt_index.source_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[0].src_pipe); |
| flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01; |
| flt_index.filter_index_list_len = 0; |
| flt_index.embedded_pipe_index_valid = 1; |
| flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD); |
| flt_index.retain_header_valid = 1; |
| flt_index.retain_header = 0; |
| flt_index.embedded_call_mux_id_valid = 1; |
| flt_index.embedded_call_mux_id = IPACM_Iface::ipacmcfg->GetQmapId(); |
| |
| if(false == m_filtering.SendFilteringRuleIndex(&flt_index)) |
| { |
| IPACMERR("Error sending filtering rule index, aborting...\n"); |
| close(fd); |
| return IPACM_FAILURE; |
| } |
| |
| memset(wan_ul_fl_rule_hdl_v4, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t)); |
| num_wan_ul_fl_rule_v4 = 0; |
| } |
| else |
| { |
| if (m_filtering.DeleteFilteringHdls(&lan_wan_fl_rule_hdl[0], IPA_IP_v4, 1) == false) |
| { |
| IPACMERR("Error Adding RuleTable(1) to Filtering, aborting...\n"); |
| close(fd); |
| return IPACM_FAILURE; |
| } |
| } |
| |
| close(fd); |
| return IPACM_SUCCESS; |
| } |
| |
| /* handle new_address event*/ |
| int IPACM_Lan::handle_addr_evt(ipacm_event_data_addr *data) |
| { |
| struct ipa_ioc_add_rt_rule *rt_rule; |
| struct ipa_rt_rule_add *rt_rule_entry; |
| struct ipa_flt_rule_add flt_rule_entry; |
| const int NUM_RULES = 1; |
| int num_ipv6_addr; |
| int res = IPACM_SUCCESS; |
| |
| /* construct ipa_ioc_add_flt_rule with v6 rules */ |
| ipa_ioc_add_flt_rule *m_pFilteringTable; |
| |
| IPACMDBG("set route/filter rule ip-type: %d \n", data->iptype); |
| |
| if (data->iptype == IPA_IP_v4) |
| { |
| rt_rule = (struct ipa_ioc_add_rt_rule *) |
| calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + |
| NUM_RULES * sizeof(struct ipa_rt_rule_add)); |
| |
| if (!rt_rule) |
| { |
| IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); |
| return IPACM_FAILURE; |
| } |
| |
| rt_rule->commit = 1; |
| rt_rule->num_rules = NUM_RULES; |
| rt_rule->ip = data->iptype; |
| rt_rule_entry = &rt_rule->rules[0]; |
| rt_rule_entry->at_rear = false; |
| rt_rule_entry->rule.dst = iface_query->excp_pipe; //go to A5 |
| rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; |
| strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name); |
| rt_rule_entry->rule.attrib.u.v4.dst_addr = data->ipv4_addr; |
| rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; |
| if (false == m_routing.AddRoutingRule(rt_rule)) |
| { |
| IPACMERR("Routing rule addition failed!\n"); |
| res = IPACM_FAILURE; |
| goto fail; |
| } |
| else if (rt_rule_entry->status) |
| { |
| IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); |
| res = rt_rule_entry->status; |
| goto fail; |
| } |
| dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl; |
| IPACMDBG("ipv4 iface rt-rule hdl1=0x%x\n", dft_rt_rule_hdl[0]); |
| /* initial multicast/broadcast/fragment filter rule */ |
| IPACM_Iface::init_fl_rule(data->iptype); |
| } |
| else |
| { |
| /* check if see that v6-addr already or not*/ |
| for(num_ipv6_addr=0;num_ipv6_addr<num_dft_rt_v6;num_ipv6_addr++) |
| { |
| if((ipv6_addr[num_ipv6_addr][0] == data->ipv6_addr[0]) && |
| (ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) && |
| (ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) && |
| (ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3])) |
| { |
| return IPACM_SUCCESS; |
| break; |
| } |
| } |
| |
| rt_rule = (struct ipa_ioc_add_rt_rule *) |
| calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + |
| NUM_RULES * sizeof(struct ipa_rt_rule_add)); |
| |
| if (!rt_rule) |
| { |
| IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); |
| return IPACM_FAILURE; |
| } |
| |
| rt_rule->commit = 1; |
| rt_rule->num_rules = NUM_RULES; |
| rt_rule->ip = data->iptype; |
| strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name); |
| |
| rt_rule_entry = &rt_rule->rules[0]; |
| rt_rule_entry->at_rear = false; |
| rt_rule_entry->rule.dst = iface_query->excp_pipe; //go to A5 |
| rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0]; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1]; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2]; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = data->ipv6_addr[3]; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; |
| rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; |
| ipv6_addr[num_dft_rt_v6][0] = data->ipv6_addr[0]; |
| ipv6_addr[num_dft_rt_v6][1] = data->ipv6_addr[1]; |
| ipv6_addr[num_dft_rt_v6][2] = data->ipv6_addr[2]; |
| ipv6_addr[num_dft_rt_v6][3] = data->ipv6_addr[3]; |
| if (false == m_routing.AddRoutingRule(rt_rule)) |
| { |
| IPACMERR("Routing rule addition failed!\n"); |
| res = IPACM_FAILURE; |
| goto fail; |
| } |
| else if (rt_rule_entry->status) |
| { |
| IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); |
| res = rt_rule_entry->status; |
| goto fail; |
| } |
| dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl; |
| |
| /* setup same rule for v6_wan table*/ |
| strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name); |
| if (false == m_routing.AddRoutingRule(rt_rule)) |
| { |
| IPACMERR("Routing rule addition failed!\n"); |
| res = IPACM_FAILURE; |
| goto fail; |
| } |
| else if (rt_rule_entry->status) |
| { |
| IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); |
| res = rt_rule_entry->status; |
| goto fail; |
| } |
| dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl; |
| |
| IPACMDBG("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, num_dft_rt_v6: %d \n", |
| dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6], |
| dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1],num_dft_rt_v6); |
| |
| if (num_dft_rt_v6 == 0) |
| { |
| /* initial multicast/broadcast/fragment filter rule */ |
| IPACM_Iface::init_fl_rule(data->iptype); |
| } |
| num_dft_rt_v6++; |
| } |
| |
| IPACMDBG("number of default route rules %d\n", num_dft_rt_v6); |
| |
| fail: |
| free(rt_rule); |
| |
| return res; |
| } |
| |
| /* configure private subnet filter rules*/ |
| int IPACM_Lan::handle_private_subnet(ipa_ip_type iptype) |
| { |
| struct ipa_flt_rule_add flt_rule_entry; |
| int i; |
| |
| ipa_ioc_add_flt_rule *m_pFilteringTable; |
| |
| IPACMDBG("lan->handle_private_subnet(); set route/filter rule \n"); |
| |
| if (rx_prop == NULL) |
| { |
| IPACMDBG("No rx properties registered for iface %s\n", dev_name); |
| return IPACM_SUCCESS; |
| } |
| |
| if (iptype == IPA_IP_v4) |
| { |
| |
| m_pFilteringTable = (struct ipa_ioc_add_flt_rule *) |
| calloc(1, |
| sizeof(struct ipa_ioc_add_flt_rule) + |
| (IPACM_Iface::ipacmcfg->ipa_num_private_subnet) * sizeof(struct ipa_flt_rule_add) |
| ); |
| if (!m_pFilteringTable) |
| { |
| PERROR("Error Locate ipa_flt_rule_add memory...\n"); |
| return IPACM_FAILURE; |
| } |
| m_pFilteringTable->commit = 1; |
| m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; |
| m_pFilteringTable->global = false; |
| m_pFilteringTable->ip = IPA_IP_v4; |
| m_pFilteringTable->num_rules = (uint8_t)IPACM_Iface::ipacmcfg->ipa_num_private_subnet; |
| |
| if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4)) |
| { |
| IPACMERR("LAN m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_lan_v4); |
| free(m_pFilteringTable); |
| return IPACM_FAILURE; |
| } |
| |
| /* Make LAN-traffic always go A5, use default IPA-RT table */ |
| if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4)) |
| { |
| IPACMERR("LAN m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_default_v4); |
| free(m_pFilteringTable); |
| return IPACM_FAILURE; |
| } |
| |
| for (i = 0; i < (IPACM_Iface::ipacmcfg->ipa_num_private_subnet); i++) |
| { |
| memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); |
| flt_rule_entry.at_rear = true; |
| flt_rule_entry.rule.retain_hdr = 1; |
| flt_rule_entry.flt_rule_hdl = -1; |
| flt_rule_entry.status = -1; |
| flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; |
| |
| /* Support priave subnet feature including guest-AP can't talk to primary AP etc */ |
| flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl; |
| IPACMDBG(" private filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_default_v4.name); |
| |
| memcpy(&flt_rule_entry.rule.attrib, |
| &rx_prop->rx[0].attrib, |
| sizeof(flt_rule_entry.rule.attrib)); |
| flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; |
| flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask; |
| flt_rule_entry.rule.attrib.u.v4.dst_addr = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr; |
| memcpy(&(m_pFilteringTable->rules[i]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); |
| IPACMDBG("Loop %d 5\n", i); |
| } |
| |
| if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) |
| { |
| IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); |
| free(m_pFilteringTable); |
| return IPACM_FAILURE; |
| } |
| |
| /* copy filter rule hdls */ |
| for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_private_subnet; i++) |
| { |
| |
| private_fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl; |
| } |
| free(m_pFilteringTable); |
| } |
| return IPACM_SUCCESS; |
| } |
| |
| /* for STA mode wan up: configure filter rule for wan_up event*/ |
| int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type) |
| { |
| struct ipa_flt_rule_add flt_rule_entry; |
| int len = 0; |
| ipa_ioc_add_flt_rule *m_pFilteringTable; |
| |
| IPACMDBG("set WAN interface as default filter rule\n"); |
| |
| if (rx_prop == NULL) |
| { |
| IPACMDBG("No rx properties registered for iface %s\n", dev_name); |
| return IPACM_SUCCESS; |
| } |
| |
| if(ip_type == IPA_IP_v4) |
| { |
| len = sizeof(struct ipa_ioc_add_flt_rule) + (1 * sizeof(struct ipa_flt_rule_add)); |
| m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len); |
| if (m_pFilteringTable == NULL) |
| { |
| PERROR("Error Locate ipa_flt_rule_add memory...\n"); |
| return IPACM_FAILURE; |
| } |
| |
| m_pFilteringTable->commit = 1; |
| m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; |
| m_pFilteringTable->global = false; |
| m_pFilteringTable->ip = IPA_IP_v4; |
| m_pFilteringTable->num_rules = (uint8_t)1; |
| |
| IPACMDBG("Retrieving routing hanle for table: %s\n", |
| IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name); |
| if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4)) |
| { |
| IPACMERR("m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4=0x%p) Failed.\n", |
| &IPACM_Iface::ipacmcfg->rt_tbl_wan_v4); |
| free(m_pFilteringTable); |
| return IPACM_FAILURE; |
| } |
| IPACMDBG("Routing hanle for table: %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl); |
| |
| |
| memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); // Zero All Fields |
| flt_rule_entry.at_rear = true; |
| flt_rule_entry.flt_rule_hdl = -1; |
| flt_rule_entry.status = -1; |
| flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; //IPA_PASS_TO_ROUTING |
| flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl; |
| |
| memcpy(&flt_rule_entry.rule.attrib, |
| &rx_prop->rx[0].attrib, |
| sizeof(flt_rule_entry.rule.attrib)); |
| |
| flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; |
| flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x0; |
| flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x0; |
| |
| memcpy(&m_pFilteringTable->rules[0], &flt_rule_entry, sizeof(flt_rule_entry)); |
| if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) |
| { |
| IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); |
| free(m_pFilteringTable); |
| return IPACM_FAILURE; |
| } |
| else |
| { |
| IPACMDBG("flt rule hdl0=0x%x, status=0x%x\n", |
| m_pFilteringTable->rules[0].flt_rule_hdl, |
| m_pFilteringTable->rules[0].status); |
| } |
| |
| |
| /* copy filter hdls */ |
| lan_wan_fl_rule_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl; |
| free(m_pFilteringTable); |
| } |
| else if(ip_type == IPA_IP_v6) |
| { |
| /* add default v6 filter rule */ |
| m_pFilteringTable = (struct ipa_ioc_add_flt_rule *) |
| calloc(1, sizeof(struct ipa_ioc_add_flt_rule) + |
| 1 * sizeof(struct ipa_flt_rule_add)); |
| |
| if (!m_pFilteringTable) |
| { |
| PERROR("Error Locate ipa_flt_rule_add memory...\n"); |
| return IPACM_FAILURE; |
| } |
| |
| m_pFilteringTable->commit = 1; |
| m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; |
| m_pFilteringTable->global = false; |
| m_pFilteringTable->ip = IPA_IP_v6; |
| m_pFilteringTable->num_rules = (uint8_t)1; |
| |
| if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_v6)) |
| { |
| IPACMERR("m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_v6=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_v6); |
| free(m_pFilteringTable); |
| return IPACM_FAILURE; |
| } |
| |
| memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); |
| |
| flt_rule_entry.at_rear = true; |
| flt_rule_entry.flt_rule_hdl = -1; |
| flt_rule_entry.status = -1; |
| flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; |
| flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_v6.hdl; |
| |
| memcpy(&flt_rule_entry.rule.attrib, |
| &rx_prop->rx[0].attrib, |
| sizeof(flt_rule_entry.rule.attrib)); |
| |
| flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; |
| flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000; |
| flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; |
| flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; |
| flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; |
| flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000; |
| flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; |
| flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; |
| flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000; |
| |
| memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); |
| if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) |
| { |
| IPACMERR("Error Adding Filtering rule, aborting...\n"); |
| free(m_pFilteringTable); |
| return IPACM_FAILURE; |
| } |
| else |
| { |
| IPACMDBG("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); |
| } |
| |
| /* copy filter hdls */ |
| dft_v6fl_rule_hdl[IPV6_DEFAULT_FILTERTING_RULES] = m_pFilteringTable->rules[0].flt_rule_hdl; |
| free(m_pFilteringTable); |
| } |
| |
| return IPACM_SUCCESS; |
| } |
| |
| int IPACM_Lan::handle_wan_up_ex(ipacm_ext_prop* ext_prop, ipa_ip_type iptype) |
| { |
| int fd, ret = IPACM_SUCCESS, cnt; |
| IPACM_Config* ipacm_config = IPACM_Iface::ipacmcfg; |
| struct ipa_ioc_write_qmapid mux; |
| |
| if(rx_prop != NULL) |
| { |
| /* give mud ID to IPA-driver for WLAN/LAN pkts */ |
| fd = open(IPA_DEVICE_NAME, O_RDWR); |
| if (0 == fd) |
| { |
| IPACMDBG("Failed opening %s.\n", IPA_DEVICE_NAME); |
| return IPACM_FAILURE; |
| } |
| |
| mux.qmap_id = ipacm_config->GetQmapId(); |
| for(cnt=0; cnt<rx_prop->num_rx_props; cnt++) |
| { |
| mux.client = rx_prop->rx[cnt].src_pipe; |
| ret = ioctl(fd, IPA_IOC_WRITE_QMAPID, &mux); |
| if (ret) |
| { |
| IPACMERR("Failed to write mux id %d\n", mux.qmap_id); |
| close(fd); |
| return IPACM_FAILURE; |
| } |
| } |
| close(fd); |
| } |
| |
| ret = handle_uplink_filter_rule(ext_prop, iptype); |
| return ret; |
| } |
| |
| |
| /*handle wlan iface down event*/ |
| int IPACM_Lan::handle_down_evt() |
| { |
| int i; |
| uint32_t tx_index; |
| int res = IPACM_SUCCESS; |
| |
| /* no iface address up, directly close iface*/ |
| if (ip_type == IPACM_IP_NULL) |
| { |
| goto fail; |
| } |
| |
| IPACMDBG("lan handle_down_evt\n "); |
| |
| if (ip_type != IPA_IP_v6) |
| { |
| if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) |
| == false) |
| { |
| IPACMERR("Routing rule deletion failed!\n"); |
| res = IPACM_FAILURE; |
| goto fail; |
| } |
| } |
| |
| IPACMDBG("Finished delete default iface ipv4 rules \n "); |
| |
| /* delete default v6 routing rule */ |
| if (ip_type != IPA_IP_v4) |
| { |
| /* may have multiple ipv6 iface-RT rules*/ |
| for (i = 0; i < 2*num_dft_rt_v6; i++) |
| { |
| if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + i], IPA_IP_v6) |
| == false) |
| { |
| IPACMERR("Routing rule deletion failed!\n"); |
| res = IPACM_FAILURE; |
| goto fail; |
| } |
| } |
| } |
| |
| IPACMDBG("Finished delete default iface ipv6 rules \n "); |
| |
| /* free unicast routing rule */ |
| if (tx_prop != NULL) |
| { |
| for (i = 0; i < num_uni_rt; i++) |
| { |
| for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) |
| { |
| if(get_rt_ruleptr(route_rule, i)->ip != tx_prop->tx[tx_index].ip) |
| { |
| IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d no unicast LAN RT-rule deleted, index: %d\n", |
| tx_index, tx_prop->tx[tx_index].ip,get_rt_ruleptr(route_rule, i)->ip,i); |
| continue; |
| } |
| |
| IPACMDBG("Tx:%d, ip-type: %d - ip-type: %d Delete unicast LAN RT-rule deleted index: %d\n", |
| tx_index, tx_prop->tx[tx_index].ip,get_rt_ruleptr(route_rule, i)->ip,i); |
| |
| if (m_routing.DeleteRoutingHdl(get_rt_ruleptr(route_rule, i)->rt_rule_hdl[tx_index], |
| get_rt_ruleptr(route_rule, i)->ip) == false) |
| { |
| IPACMERR("Routing rule 0x%x deletion failed!\n",get_rt_ruleptr(route_rule, i)->rt_rule_hdl[tx_index]); |
| res = IPACM_FAILURE; |
| goto fail; |
| } |
| } |
| |
| } |
| } |
| |
| /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete all IPV4V6 RT-rule */ |
| IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); |
| |
| /* check software routing fl rule hdl */ |
| if (softwarerouting_act == true && rx_prop != NULL) |
| { |
| handle_software_routing_disable(); |
| } |
| |
| |
| /* delete default filter rules */ |
| if (ip_type != IPA_IP_v6 && rx_prop != NULL) |
| { |
| if (m_filtering.DeleteFilteringHdls(dft_v4fl_rule_hdl, |
| IPA_IP_v4, |
| IPV4_DEFAULT_FILTERTING_RULES) == false) |
| { |
| IPACMERR("Error Adding Filtering Rule, aborting...\n"); |
| res = IPACM_FAILURE; |
| goto fail; |
| } |
| |
| /* free private-subnet ipv4 filter rules */ |
| if (m_filtering.DeleteFilteringHdls( |
| private_fl_rule_hdl, |
| IPA_IP_v4, |
| IPACM_Iface::ipacmcfg->ipa_num_private_subnet) == false) |
| { |
| IPACMERR("Error Deleting RuleTable(1) to Filtering, aborting...\n"); |
| res = IPACM_FAILURE; |
| goto fail; |
| } |
| } |
| |
| IPACMDBG("Finished delete default iface ipv4 filtering rules \n "); |
| |
| if (ip_type != IPA_IP_v4 && rx_prop != NULL) |
| { |
| if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl, |
| IPA_IP_v6, |
| (IPV6_DEFAULT_FILTERTING_RULES + IPV6_DEFAULT_LAN_FILTERTING_RULES)) == false) |
| { |
| IPACMERR("Error Adding RuleTable(1) to Filtering, aborting...\n"); |
| res = IPACM_FAILURE; |
| goto fail; |
| } |
| } |
| |
| IPACMDBG("Finished delete default iface ipv6 filtering rules \n "); |
| |
| /* delete wan filter rule */ |
| if (IPACM_Wan::isWanUP() && rx_prop != NULL) |
| { |
| IPACMDBG("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode); |
| handle_wan_down(IPACM_Wan::backhaul_is_sta_mode); |
| } |
| |
| if (IPACM_Wan::isWanUP_V6() && rx_prop != NULL) |
| { |
| IPACMDBG("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode); |
| handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode); |
| } |
| |
| fail: |
| /* Delete corresponding ipa_rm_resource_name of RX-endpoint after delete all IPV4V6 FT-rule */ |
| IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]); |
| |
| if (tx_prop != NULL) |
| { |
| free(tx_prop); |
| } |
| if (rx_prop != NULL) |
| { |
| free(rx_prop); |
| } |
| if (iface_query != NULL) |
| { |
| free(iface_query); |
| } |
| |
| return res; |
| } |
| |
| /* install UL filter rule from Q6 */ |
| int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop* prop, ipa_ip_type iptype) |
| { |
| ipa_flt_rule_add flt_rule_entry; |
| int len = 0, cnt, ret = IPACM_SUCCESS; |
| ipa_ioc_add_flt_rule *pFilteringTable; |
| ipa_fltr_installed_notif_req_msg_v01 flt_index; |
| int fd; |
| int i; |
| |
| IPACMDBG("Set extended property rules in LAN\n"); |
| |
| if (rx_prop == NULL) |
| { |
| IPACMDBG("No rx properties registered for iface %s\n", dev_name); |
| return IPACM_SUCCESS; |
| } |
| |
| if(prop == NULL || prop->num_ext_props <= 0) |
| { |
| IPACMDBG("No extended property.\n"); |
| return IPACM_SUCCESS; |
| } |
| |
| fd = open(IPA_DEVICE_NAME, O_RDWR); |
| if (0 == fd) |
| { |
| IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); |
| } |
| |
| memset(&flt_index, 0, sizeof(flt_index)); |
| flt_index.source_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[0].src_pipe); |
| flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01; |
| flt_index.filter_index_list_len = prop->num_ext_props; |
| flt_index.embedded_pipe_index_valid = 1; |
| flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD); |
| flt_index.retain_header_valid = 1; |
| flt_index.retain_header = 0; |
| flt_index.embedded_call_mux_id_valid = 1; |
| flt_index.embedded_call_mux_id = IPACM_Iface::ipacmcfg->GetQmapId(); |
| |
| IPACMDBG("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d\n", flt_index.source_pipe_index, |
| flt_index.filter_index_list_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id); |
| |
| len = sizeof(struct ipa_ioc_add_flt_rule) + prop->num_ext_props * sizeof(struct ipa_flt_rule_add); |
| pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len); |
| if (pFilteringTable == NULL) |
| { |
| IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); |
| return IPACM_FAILURE; |
| } |
| memset(pFilteringTable, 0, len); |
| |
| pFilteringTable->commit = 1; |
| pFilteringTable->ep = rx_prop->rx[0].src_pipe; |
| pFilteringTable->global = false; |
| pFilteringTable->ip = iptype; |
| pFilteringTable->num_rules = prop->num_ext_props; |
| |
| memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); // Zero All Fields |
| flt_rule_entry.at_rear = 1; |
| flt_rule_entry.flt_rule_hdl = -1; |
| flt_rule_entry.status = -1; |
| |
| flt_rule_entry.rule.retain_hdr = 0; |
| flt_rule_entry.rule.to_uc = 0; |
| flt_rule_entry.rule.eq_attrib_type = 1; |
| if(iptype == IPA_IP_v4) |
| flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; |
| else if(iptype == IPA_IP_v6) |
| flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; |
| else |
| { |
| IPACMERR("IP type is not expected.\n"); |
| ret = IPACM_FAILURE; |
| goto fail; |
| } |
| |
| for(cnt=0; cnt<prop->num_ext_props; cnt++) |
| { |
| memcpy(&flt_rule_entry.rule.eq_attrib, |
| &prop->prop[cnt].eq_attrib, |
| sizeof(prop->prop[cnt].eq_attrib)); |
| flt_rule_entry.rule.rt_tbl_idx = prop->prop[cnt].rt_tbl_idx; |
| memcpy(&pFilteringTable->rules[cnt], &flt_rule_entry, sizeof(flt_rule_entry)); |
| |
| flt_index.filter_index_list[cnt].filter_index = flt_rule_count; |
| flt_index.filter_index_list[cnt].filter_handle = prop->prop[cnt].filter_hdl; |
| |
| IPACMDBG("Filtering rule %d, index %d\n", cnt, flt_index.filter_index_list[cnt].filter_index); |
| |
| flt_rule_count++; |
| } |
| |
| if(false == m_filtering.SendFilteringRuleIndex(&flt_index)) |
| { |
| IPACMERR("Error sending filtering rule index, aborting...\n"); |
| ret = IPACM_FAILURE; |
| goto fail; |
| } |
| |
| if(false == m_filtering.AddFilteringRule(pFilteringTable)) |
| { |
| IPACMERR("Error Adding RuleTable to Filtering, aborting...\n"); |
| ret = IPACM_FAILURE; |
| goto fail; |
| } |
| else |
| { |
| if(iptype == IPA_IP_v4) |
| { |
| for(i=0; i<pFilteringTable->num_rules; i++) |
| { |
| wan_ul_fl_rule_hdl_v4[num_wan_ul_fl_rule_v4] = pFilteringTable->rules[i].flt_rule_hdl; |
| num_wan_ul_fl_rule_v4++; |
| } |
| } |
| else if(iptype == IPA_IP_v6) |
| { |
| for(i=0; i<pFilteringTable->num_rules; i++) |
| { |
| wan_ul_fl_rule_hdl_v6[num_wan_ul_fl_rule_v6] = pFilteringTable->rules[i].flt_rule_hdl; |
| num_wan_ul_fl_rule_v6++; |
| } |
| } |
| else |
| { |
| IPACMERR("IP type is not expected.\n"); |
| goto fail; |
| } |
| } |
| |
| fail: |
| free(pFilteringTable); |
| close(fd); |
| return ret; |
| } |
| |
| int IPACM_Lan::handle_wan_down_v6(bool is_sta_mode) |
| { |
| ipa_fltr_installed_notif_req_msg_v01 flt_index; |
| int fd; |
| |
| fd = open(IPA_DEVICE_NAME, O_RDWR); |
| if (0 == fd) |
| { |
| IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); |
| return IPACM_FAILURE; |
| } |
| |
| if(is_sta_mode == false) |
| { |
| if (m_filtering.DeleteFilteringHdls(wan_ul_fl_rule_hdl_v6, |
| IPA_IP_v6, num_wan_ul_fl_rule_v6) == false) |
| { |
| IPACMERR("Error Deleting RuleTable(1) to Filtering, aborting...\n"); |
| close(fd); |
| return IPACM_FAILURE; |
| } |
| |
| memset(&flt_index, 0, sizeof(flt_index)); |
| flt_index.source_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[0].src_pipe); |
| flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01; |
| flt_index.filter_index_list_len = 0; |
| flt_index.embedded_pipe_index_valid = 1; |
| flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD); |
| flt_index.retain_header_valid = 1; |
| flt_index.retain_header = 0; |
| flt_index.embedded_call_mux_id_valid = 1; |
| flt_index.embedded_call_mux_id = IPACM_Iface::ipacmcfg->GetQmapId(); |
| |
| if(false == m_filtering.SendFilteringRuleIndex(&flt_index)) |
| { |
| IPACMERR("Error sending filtering rule index, aborting...\n"); |
| close(fd); |
| return IPACM_FAILURE; |
| } |
| |
| memset(wan_ul_fl_rule_hdl_v6, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t)); |
| num_wan_ul_fl_rule_v6 = 0; |
| } |
| else |
| { |
| if (m_filtering.DeleteFilteringHdls(&dft_v6fl_rule_hdl[IPV6_DEFAULT_FILTERTING_RULES], |
| IPA_IP_v6, 1) == false) |
| { |
| IPACMERR("Error Adding RuleTable(1) to Filtering, aborting...\n"); |
| close(fd); |
| return IPACM_FAILURE; |
| } |
| } |
| |
| close(fd); |
| return IPACM_SUCCESS; |
| } |