blob: 032a11f6f4b1e22f5ae57515ae1db08ba3180d39 [file] [log] [blame]
/*
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_Wan.cpp
@brief
This file implements the WAN iface functionality.
@Author
Skylar Chang
*/
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <IPACM_Wan.h>
#include <IPACM_Xml.h>
#include <IPACM_Log.h>
#include "IPACM_EvtDispatcher.h"
#include <IPACM_IfaceManager.h>
#include "linux/rmnet_ipa_fd_ioctl.h"
#include "IPACM_Config.h"
#include "IPACM_Defs.h"
bool IPACM_Wan::wan_up = false;
bool IPACM_Wan::wan_up_v6 = false;
int IPACM_Wan::num_v4_flt_rule = 0;
int IPACM_Wan::num_v6_flt_rule = 0;
struct ipa_flt_rule_add IPACM_Wan::flt_rule_v4[IPA_MAX_FLT_RULE];
struct ipa_flt_rule_add IPACM_Wan::flt_rule_v6[IPA_MAX_FLT_RULE];
bool IPACM_Wan::backhaul_is_sta_mode = false;
bool IPACM_Wan::is_ext_prop_set = false;
IPACM_Wan::IPACM_Wan(int iface_index, int is_sta_mode) : IPACM_Iface(iface_index)
{
num_firewall_v4 = 0;
num_firewall_v6 = 0;
if(iface_query != NULL)
{
wan_route_rule_v4_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t));
wan_route_rule_v6_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t));
wan_route_rule_v6_hdl_a5 = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t));
IPACMDBG("IPACM->IPACM_Wan(%d) constructor: Tx:%d\n", ipa_if_num, iface_query->num_tx_props);
}
m_is_sta_mode = is_sta_mode;
active_v4 = false;
active_v6 = false;
header_set_v4 = false;
header_set_v6 = false;
header_partial_default_wan_v4 = false;
header_partial_default_wan_v6 = false;
hdr_hdl_sta_v4 = 0;
hdr_hdl_sta_v6 = 0;
if(m_is_sta_mode == 0)
{
IPACMDBG("The new WAN interface is modem.\n");
query_ext_prop();
}
else
{
IPACMDBG("The new WAN interface is WLAN STA.\n");
}
m_fd_ipa = open(IPA_DEVICE_NAME, O_RDWR);
if(0 == m_fd_ipa)
{
IPACMERR("Failed to open %s\n",IPA_DEVICE_NAME);
}
return;
}
IPACM_Wan::~IPACM_Wan()
{
IPACM_EvtDispatcher::deregistr(this);
IPACM_IfaceManager::deregistr(this);
return;
}
/* handle new_address event */
int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data)
{
struct ipa_ioc_add_rt_rule *rt_rule;
struct ipa_rt_rule_add *rt_rule_entry;
const int NUM_RULES = 1;
int num_ipv6_addr;
int res = IPACM_SUCCESS;
if (data->iptype == IPA_IP_v6)
{
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]))
{
IPACMDBG("find matched ipv6 address, index:%d \n", num_ipv6_addr);
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)
{
if(m_is_sta_mode == 0)
{
init_fl_rule_ex(data->iptype);
}
else
{
init_fl_rule(data->iptype);
}
}
num_dft_rt_v6++;
}
else
{
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;
/* still need setup v4 default routing rule to A5*/
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 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[0]);
/* initial multicast/broadcast/fragment filter rule */
if(m_is_sta_mode == 0)
{
init_fl_rule_ex(data->iptype);
}
else
{
init_fl_rule(data->iptype);
}
wan_v4_addr = data->ipv4_addr;
IPACMDBG("Receved wan address:0x%x\n",wan_v4_addr);
}
IPACMDBG("number of default route rules %d\n", num_dft_rt_v6);
fail:
free(rt_rule);
return res;
}
void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param)
{
int ipa_interface_index;
switch (event)
{
case IPA_WLAN_LINK_DOWN_EVENT:
{
if(m_is_sta_mode == 1)
{
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_WLAN_LINK_DOWN_EVENT\n");
handle_down_evt();
/* reset the STA-iface category to unknown */
IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat = UNKNOWN_IF;
IPACMDBG("ipa_WAN (%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_CFG_CHANGE_EVENT:
{
if ( (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat != ipa_if_cate) &&
(m_is_sta_mode ==2))
{
IPACMDBG("Received IPA_CFG_CHANGE_EVENT and category changed(sta_mode:%d)\n", m_is_sta_mode);
/* posting link-up event for cradle use-case */
ipacm_cmd_q_data evt_data;
memset(&evt_data, 0, sizeof(evt_data));
ipacm_event_data_fid *data_fid = NULL;
data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid));
if(data_fid == NULL)
{
IPACMERR("unable to allocate memory for IPA_USB_LINK_UP_EVENT data_fid\n");
return NULL;
}
if(IPACM_Iface::ipa_get_if_index(dev_name, &(data_fid->if_index)))
{
IPACMERR("Error while getting interface index for %s device", dev_name);
}
evt_data.event = IPA_USB_LINK_UP_EVENT;
evt_data.evt_data = data_fid;
IPACMDBG("Posting event:%d\n", evt_data.event);
IPACM_EvtDispatcher::PostEvt(&evt_data);
/* delete previous instance */
handle_down_evt();
IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
delete this;
return;
}
}
break;
case IPA_LINK_DOWN_EVENT:
{
if(m_is_sta_mode == 0)
{
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_ex();
IPACMDBG("ipa_WAN (%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("Get IPA_ADDR_ADD_EVENT: IF ip type %d, incoming ip type %d\n", ip_type, data->iptype);
/* 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);
}
}
}
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);
if (ipa_interface_index == ipa_if_num)
{
IPACMDBG("Received IPA_ROUTE_ADD_EVENT\n");
IPACMDBG("ipv4 addr 0x%x\n", data->ipv4_addr);
IPACMDBG("ipv4 addr mask 0x%x\n", data->ipv4_addr_mask);
/* The special below condition is to handle default gateway */
if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == false))
{
IPACMDBG("adding routing table\n");
handle_route_add_evt(data->iptype);
}
else if ((data->iptype == IPA_IP_v6) &&
(!data->ipv6_addr[0]) && (!data->ipv6_addr[1]) && (!data->ipv6_addr[2]) && (!data->ipv6_addr[3]) && (active_v6 == false))
{
IPACMDBG("\n get default v6 route (dst:00.00.00.00)\n");
IPACMDBG(" IPV6 value: %08x:%08x:%08x:%08x \n",
data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]);
handle_route_add_evt(data->iptype);
}
}
}
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);
if (ipa_interface_index == ipa_if_num)
{
IPACMDBG("Received IPA_ROUTE_DEL_EVENT\n");
if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == true))
{
IPACMDBG("get del default v4 route (dst:0.0.0.0)\n");
if(m_is_sta_mode == 0)
{
del_wan_firewall_rule(IPA_IP_v4);
install_wan_filtering_rule();
handle_route_del_evt_ex(IPA_IP_v4);
}
else
{
del_dft_firewall_rules(IPA_IP_v4);
handle_route_del_evt(IPA_IP_v4);
}
}
else if ((data->iptype == IPA_IP_v6) && (!data->ipv6_addr[0]) && (!data->ipv6_addr[1]) && (!data->ipv6_addr[2]) && (!data->ipv6_addr[3]) && (active_v6 == true))
{
IPACMDBG("get del default v6 route (dst:00.00.00.00)\n");
if(m_is_sta_mode == 0)
{
del_wan_firewall_rule(IPA_IP_v6);
install_wan_filtering_rule();
handle_route_del_evt_ex(IPA_IP_v6);
}
else
{
del_dft_firewall_rules(IPA_IP_v6);
handle_route_del_evt(IPA_IP_v6);
}
}
}
}
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)
{
IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT in STA mode\n");
handle_header_add_evt(data->mac_addr);
}
}
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;
case IPA_FIREWALL_CHANGE_EVENT:
IPACMDBG("Received IPA_FIREWALL_CHANGE_EVENT\n");
if(m_is_sta_mode == 0)
{
if(ip_type == IPA_IP_v4)
{
del_wan_firewall_rule(IPA_IP_v4);
config_wan_firewall_rule(IPA_IP_v4);
install_wan_filtering_rule();
}
else if(ip_type == IPA_IP_v6)
{
del_wan_firewall_rule(IPA_IP_v6);
config_wan_firewall_rule(IPA_IP_v6);
install_wan_filtering_rule();
}
else if(ip_type == IPA_IP_MAX)
{
del_wan_firewall_rule(IPA_IP_v4);
config_wan_firewall_rule(IPA_IP_v4);
del_wan_firewall_rule(IPA_IP_v6);
config_wan_firewall_rule(IPA_IP_v6);
install_wan_filtering_rule();
}
else
{
IPACMERR("IP type is not expected.\n");
}
}
else
{
if (active_v4)
{
del_dft_firewall_rules(IPA_IP_v4);
config_dft_firewall_rules(IPA_IP_v4);
}
if (active_v6)
{
del_dft_firewall_rules(IPA_IP_v6);
config_dft_firewall_rules(IPA_IP_v6);
}
}
break;
default:
break;
}
return;
}
/* wan default route/filter rule configuration */
int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype)
{
/* add default WAN route */
struct ipa_ioc_add_rt_rule *rt_rule;
struct ipa_rt_rule_add *rt_rule_entry;
struct ipa_ioc_get_hdr sRetHeader;
uint32_t cnt, tx_index = 0;
const int NUM = 1;
ipacm_cmd_q_data evt_data;
struct ipa_ioc_copy_hdr sCopyHeader; /* checking if partial header*/
IPACMDBG("ip-type:%d\n", iptype);
/* copy header from tx-property, see if partial or not */
/* assume all tx-property uses the same header name for v4 or v6*/
if(tx_prop == NULL)
{
IPACMDBG("No tx properties, ignore default route setting\n");
return IPACM_SUCCESS;
}
if (m_is_sta_mode !=0)
{
IPACM_Wan::backhaul_is_sta_mode = true;
if((iptype==IPA_IP_v4) && (header_set_v4 != true))
{
header_partial_default_wan_v4 = true;
IPACMDBG("STA ipv4-header haven't constructed \n");
return IPACM_SUCCESS;
}
else if((iptype==IPA_IP_v6) && (header_set_v6 != true))
{
header_partial_default_wan_v6 = true;
IPACMDBG("STA ipv6-header haven't constructed \n");
return IPACM_SUCCESS;
}
}
for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
{
if(tx_prop->tx[cnt].ip==iptype)
break;
}
if(tx_prop->tx[cnt].hdr_name != NULL)
{
memset(&sCopyHeader, 0, sizeof(sCopyHeader));
memcpy(sCopyHeader.name,
tx_prop->tx[cnt].hdr_name,
sizeof(sCopyHeader.name));
IPACMDBG("header name: %s\n", sCopyHeader.name);
if (m_header.CopyHeader(&sCopyHeader) == false)
{
IPACMERR("ioctl copy header failed");
return IPACM_FAILURE;
}
IPACMDBG("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
if(sCopyHeader.is_partial)
{
IPACMDBG("Not setup default WAN routing rules cuz the header is not complete\n");
if(iptype==IPA_IP_v4)
{
header_partial_default_wan_v4 = true;
}
else
{
header_partial_default_wan_v6 = true;
}
return IPACM_SUCCESS;
}
else
{
if(iptype==IPA_IP_v4)
{
header_partial_default_wan_v4 = false;
}
else
{
header_partial_default_wan_v6 = false;
}
}
}
rt_rule = (struct ipa_ioc_add_rt_rule *)
calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
NUM * 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 = (uint8_t)NUM;
rt_rule->ip = iptype;
IPACMDBG(" WAN table created %s \n", rt_rule->rt_tbl_name);
rt_rule_entry = &rt_rule->rules[0];
rt_rule_entry->at_rear = true;
if(m_is_sta_mode != 0)
{
IPACMDBG(" WAN instance is in STA mode \n");
for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
{
if(iptype != tx_prop->tx[tx_index].ip)
{
IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n",
tx_index, tx_prop->tx[tx_index].ip,iptype);
continue;
}
if (iptype == IPA_IP_v4)
{
strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name);
}
else
{
strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name);
}
if (tx_prop->tx[tx_index].hdr_name != NULL)
{
IPACMDBG(" TX- header hdl %s \n", 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("\n 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 (iptype == IPA_IP_v4)
{
rt_rule_entry->rule.attrib.u.v4.dst_addr = 0;
rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0;
if (false == m_routing.AddRoutingRule(rt_rule))
{
IPACMERR("Routing rule addition failed!\n");
free(rt_rule);
return IPACM_FAILURE;
}
wan_route_rule_v4_hdl[tx_index] = rt_rule_entry->rt_rule_hdl;
IPACMDBG("Got ipv4 wan-route rule hdl:0x%x,tx:%d,ip-type: %d \n",
wan_route_rule_v4_hdl[tx_index],
tx_index,
iptype);
}
else
{
rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0;
rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0;
rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0;
rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0;
rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0;
rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0;
rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0;
rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0;
if (false == m_routing.AddRoutingRule(rt_rule))
{
IPACMERR("Routing rule addition failed!\n");
free(rt_rule);
return IPACM_FAILURE;
}
wan_route_rule_v6_hdl[tx_index] = rt_rule_entry->rt_rule_hdl;
IPACMDBG("Set ipv6 wan-route rule hdl for v6_lan_table:0x%x,tx:%d,ip-type: %d \n",
wan_route_rule_v6_hdl[tx_index],
tx_index,
iptype);
}
}
}
/* add a catch-all rule in wan dl routing table */
if (iptype == IPA_IP_v6)
{
strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name);
memset(rt_rule_entry, 0, sizeof(struct ipa_rt_rule_add));
rt_rule_entry->at_rear = true;
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] = 0;
rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0;
rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0;
rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0;
rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0;
rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0;
rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0;
rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0;
if (false == m_routing.AddRoutingRule(rt_rule))
{
IPACMERR("Routing rule addition failed!\n");
free(rt_rule);
return IPACM_FAILURE;
}
wan_route_rule_v6_hdl_a5[0] = rt_rule_entry->rt_rule_hdl;
IPACMDBG("Set ipv6 wan-route rule hdl for v6_wan_table:0x%x,tx:%d,ip-type: %d \n",
wan_route_rule_v6_hdl_a5[0],
0,
iptype);
}
ipacm_event_iface_up *wanup_data;
wanup_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up));
if (wanup_data == NULL)
{
IPACMERR("Unable to allocate memory\n");
return IPACM_FAILURE;
}
memset(wanup_data, 0, sizeof(ipacm_event_iface_up));
if (iptype == IPA_IP_v4)
{
IPACM_Wan::wan_up = true;
active_v4 = true;
if(m_is_sta_mode == 0)
{
config_wan_firewall_rule(IPA_IP_v4);
install_wan_filtering_rule();
}
else
{
config_dft_firewall_rules(IPA_IP_v4);
}
memcpy(wanup_data->ifname, dev_name, sizeof(wanup_data->ifname));
wanup_data->ipv4_addr = wan_v4_addr;
if (m_is_sta_mode!=0)
{
wanup_data->is_sta = true;
}
else
{
wanup_data->is_sta = false;
}
IPACMDBG("Posting IPA_HANDLE_WAN_UP with below information:\n");
IPACMDBG("if_name:%s, ipv4_address:0x%x, is sta mode:%d\n",
wanup_data->ifname, wanup_data->ipv4_addr, wanup_data->is_sta);
memset(&evt_data, 0, sizeof(evt_data));
evt_data.event = IPA_HANDLE_WAN_UP;
evt_data.evt_data = (void *)wanup_data;
IPACM_EvtDispatcher::PostEvt(&evt_data);
}
else
{
IPACM_Wan::wan_up_v6 = true;
active_v6 = true;
if(m_is_sta_mode == 0)
{
config_wan_firewall_rule(IPA_IP_v6);
install_wan_filtering_rule();
}
else
{
config_dft_firewall_rules(IPA_IP_v6);
}
memcpy(wanup_data->ifname, dev_name, sizeof(wanup_data->ifname));
if (m_is_sta_mode!=0)
{
wanup_data->is_sta = true;
}
else
{
wanup_data->is_sta = false;
}
IPACMDBG("Posting IPA_HANDLE_WAN_UP_V6 with below information:\n");
IPACMDBG("if_name:%s, is sta mode: %d\n", wanup_data->ifname, wanup_data->is_sta);
memset(&evt_data, 0, sizeof(evt_data));
evt_data.event = IPA_HANDLE_WAN_UP_V6;
evt_data.evt_data = (void *)wanup_data;
IPACM_EvtDispatcher::PostEvt(&evt_data);
}
/* 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);
return IPACM_SUCCESS;
}
/* construct complete ethernet header */
int IPACM_Wan::handle_header_add_evt(uint8_t mac_addr[6])
{
#define WAN_IFACE_INDEX_LEN 2
uint32_t tx_index,cnt;
int res = IPACM_SUCCESS, len = 0;
char index[WAN_IFACE_INDEX_LEN];
struct ipa_ioc_copy_hdr sCopyHeader;
struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL;
/* start of adding header */
IPACMDBG("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
mac_addr[0], mac_addr[1], mac_addr[2],
mac_addr[3], mac_addr[4], mac_addr[5]);
if((header_set_v4 == true) || (header_set_v6 == true))
{
IPACMDBG("Already add STA full header\n");
return IPACM_SUCCESS;
}
/* add header to IPA */
len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add));
pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len);
if (pHeaderDescriptor == NULL)
{
IPACMERR("calloc failed to allocate pHeaderDescriptor\n");
return IPACM_FAILURE;
}
/* copy partial header for v4 */
for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
{
if(tx_prop->tx[cnt].ip==IPA_IP_v4)
{
memset(&sCopyHeader, 0, sizeof(sCopyHeader));
memcpy(sCopyHeader.name,
tx_prop->tx[cnt].hdr_name,
sizeof(sCopyHeader.name));
IPACMDBG("header name: %s from tx: %d\n", sCopyHeader.name,cnt);
if (m_header.CopyHeader(&sCopyHeader) == false)
{
IPACMERR("ioctl copy header failed");
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE)
{
IPACMERR("header oversize\n");
res = IPACM_FAILURE;
goto fail;
}
else
{
memcpy(pHeaderDescriptor->hdr[0].hdr,
sCopyHeader.hdr,
sCopyHeader.hdr_len);
}
/* copy client mac_addr to partial header */
memcpy(&pHeaderDescriptor->hdr[0].hdr[IPA_WLAN_PARTIAL_HDR_OFFSET], mac_addr,
IPA_MAC_ADDR_SIZE); /* only copy 6 bytes mac-address */
pHeaderDescriptor->commit = true;
pHeaderDescriptor->num_hdrs = 1;
memset(pHeaderDescriptor->hdr[0].name, 0,
sizeof(pHeaderDescriptor->hdr[0].name));
snprintf(index,sizeof(index), "%d", ipa_if_num);
strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name));
if ( strlcat(pHeaderDescriptor->hdr[0].name, IPA_WAN_PARTIAL_HDR_NAME_v4, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX)
{
IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name));
res = IPACM_FAILURE;
goto fail;
}
pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len;
pHeaderDescriptor->hdr[0].hdr_hdl = -1;
pHeaderDescriptor->hdr[0].is_partial = 0;
pHeaderDescriptor->hdr[0].status = -1;
if (m_header.AddHeader(pHeaderDescriptor) == false ||
pHeaderDescriptor->hdr[0].status != 0)
{
IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status);
res = IPACM_FAILURE;
goto fail;
}
else
{
hdr_hdl_sta_v4 = pHeaderDescriptor->hdr[0].hdr_hdl;
header_set_v4 = true;
IPACMDBG("add full header name: %s (%x)\n", pHeaderDescriptor->hdr[0].name, pHeaderDescriptor->hdr[0].hdr_hdl);
}
/* copy ipv4 full header to each TX endpoint property*/
for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
{
if(tx_prop->tx[tx_index].ip==IPA_IP_v4)
{
memcpy(tx_prop->tx[tx_index].hdr_name, pHeaderDescriptor->hdr[0].name,
sizeof(tx_prop->tx[tx_index].hdr_name));
IPACMDBG("replace full header name: %s (%x) in tx:%d\n", tx_prop->tx[tx_index].hdr_name, pHeaderDescriptor->hdr[0].hdr_hdl,tx_index);
}
}
break;
}
}
/* copy partial header for v6 */
for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
{
if(tx_prop->tx[cnt].ip == IPA_IP_v6)
{
IPACMDBG("Got partial v6-header name from %d tx props\n", cnt);
memset(&sCopyHeader, 0, sizeof(sCopyHeader));
memcpy(sCopyHeader.name,
tx_prop->tx[cnt].hdr_name,
sizeof(sCopyHeader.name));
IPACMDBG("header name: %s from tx: %d\n", sCopyHeader.name,cnt);
if (m_header.CopyHeader(&sCopyHeader) == false)
{
IPACMERR("ioctl copy header failed");
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE)
{
IPACMERR("header oversize\n");
res = IPACM_FAILURE;
goto fail;
}
else
{
memcpy(pHeaderDescriptor->hdr[0].hdr,
sCopyHeader.hdr,
sCopyHeader.hdr_len);
}
/* copy client mac_addr to partial header */
memcpy(&pHeaderDescriptor->hdr[0].hdr[IPA_WLAN_PARTIAL_HDR_OFFSET], mac_addr,
IPA_MAC_ADDR_SIZE); /* only copy 6 bytes mac-address */
pHeaderDescriptor->commit = true;
pHeaderDescriptor->num_hdrs = 1;
memset(pHeaderDescriptor->hdr[0].name, 0,
sizeof(pHeaderDescriptor->hdr[0].name));
snprintf(index,sizeof(index), "%d", ipa_if_num);
strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name));
if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_WAN_PARTIAL_HDR_NAME_v6, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX)
{
IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name));
res = IPACM_FAILURE;
goto fail;
}
pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len;
pHeaderDescriptor->hdr[0].hdr_hdl = -1;
pHeaderDescriptor->hdr[0].is_partial = 0;
pHeaderDescriptor->hdr[0].status = -1;
if (m_header.AddHeader(pHeaderDescriptor) == false ||
pHeaderDescriptor->hdr[0].status != 0)
{
IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status);
res = IPACM_FAILURE;
goto fail;
}
else
{
header_set_v6 = true;
hdr_hdl_sta_v6 = pHeaderDescriptor->hdr[0].hdr_hdl;
IPACMDBG("add full header name: %s (%x)\n", pHeaderDescriptor->hdr[0].name, pHeaderDescriptor->hdr[0].hdr_hdl);
}
/* copy ipv6 full header to each TX endpoint property*/
for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
{
if(tx_prop->tx[tx_index].ip==IPA_IP_v6)
{
memcpy(tx_prop->tx[tx_index].hdr_name, pHeaderDescriptor->hdr[0].name,
sizeof(tx_prop->tx[tx_index].hdr_name));
IPACMDBG("replace full header name: %s (%x) in tx:%d\n", tx_prop->tx[tx_index].hdr_name, pHeaderDescriptor->hdr[0].hdr_hdl,tx_index);
}
}
break;
}
}
/* see if default routes are setup before constructing full header */
if(header_partial_default_wan_v4 == true)
{
handle_route_add_evt(IPA_IP_v4);
}
if(header_partial_default_wan_v6 == true)
{
handle_route_add_evt(IPA_IP_v6);
}
fail:
free(pHeaderDescriptor);
return res;
}
/* for STA mode: add firewall rules */
int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype)
{
struct ipa_flt_rule_add flt_rule_entry;
int i, rule_v4 = 0, rule_v6 = 0;
IPACMDBG("ip-family: %d; \n", iptype);
if (rx_prop == NULL)
{
IPACMDBG("No rx properties registered for iface %s\n", dev_name);
return IPACM_SUCCESS;
}
/* default firewall is disable and the rule action is drop */
memset(&firewall_config, 0, sizeof(firewall_config));
strncpy(firewall_config.firewall_config_file, "/etc/mobileap_firewall.xml", sizeof(firewall_config.firewall_config_file));
if (firewall_config.firewall_config_file)
{
IPACMDBG("Firewall XML file is %s \n", firewall_config.firewall_config_file);
if (IPACM_SUCCESS == IPACM_read_firewall_xml(firewall_config.firewall_config_file, &firewall_config))
{
IPACMDBG("QCMAP Firewall XML read OK \n");
/* find the number of v4/v6 firewall rules */
for (i = 0; i < firewall_config.num_extd_firewall_entries; i++)
{
if (firewall_config.extd_firewall_entries[i].ip_vsn == 4)
{
rule_v4++;
}
else
{
rule_v6++;
}
}
IPACMDBG("firewall rule v4:%d v6:%d total:%d\n", rule_v4, rule_v6, firewall_config.num_extd_firewall_entries);
}
else
{
IPACMERR("QCMAP Firewall XML read failed, no that file, use default configuration \n");
}
}
else
{
IPACMERR("No firewall xml mentioned \n");
return IPACM_FAILURE;
}
/* construct ipa_ioc_add_flt_rule with N firewall rules */
ipa_ioc_add_flt_rule *m_pFilteringTable;
if (iptype == IPA_IP_v4)
{
if (rule_v4 == 0)
{
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)
{
IPACMERR("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;
memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4))
{
IPACMERR("m_routing.GetRoutingTable(rt_tbl_lan_v4) Failed.\n");
free(m_pFilteringTable);
return IPACM_FAILURE;
}
flt_rule_entry.flt_rule_hdl = -1;
flt_rule_entry.status = -1;
/* firewall disable, all traffic are allowed */
if(firewall_config.firewall_enable == true)
{
flt_rule_entry.at_rear = true;
/* default action for v4 is go DST_NAT unless user set to exception*/
if(firewall_config.rule_action_accept == true)
{
flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
}
else
{
flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
}
}
else
{
flt_rule_entry.at_rear = true;
flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
}
flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
memcpy(&flt_rule_entry.rule.attrib,
&rx_prop->rx[0].attrib,
sizeof(struct ipa_rule_attrib));
flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000;
flt_rule_entry.rule.attrib.u.v4.dst_addr = 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 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 */
dft_wan_fl_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl;
free(m_pFilteringTable);
}
else
{
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 == NULL)
{
IPACMERR("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("Retreiving Routing handle for routing table name:%s\n",
IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name);
if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4))
{
IPACMERR("m_routing.GetRoutingTable(&rt_tbl_lan_v4=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_lan_v4);
free(m_pFilteringTable);
return IPACM_FAILURE;
}
IPACMDBG("Routing handle for wan routing table:0x%x\n", IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl);
if(firewall_config.firewall_enable == true)
{
rule_v4 = 0;
for (i = 0; i < firewall_config.num_extd_firewall_entries; i++)
{
if (firewall_config.extd_firewall_entries[i].ip_vsn == 4)
{
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.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
/* Accept v4 matched rules*/
if(firewall_config.rule_action_accept == true)
{
flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
}
else
{
flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
}
memcpy(&flt_rule_entry.rule.attrib,
&firewall_config.extd_firewall_entries[i].attrib,
sizeof(struct ipa_rule_attrib));
IPACMDBG("rx property attrib mask: 0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask;
flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask;
flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data;
/* check if the rule is define as TCP_UDP, split into 2 rules, 1 for TCP and 1 UDP */
if (firewall_config.extd_firewall_entries[i].attrib.u.v4.protocol
== IPACM_FIREWALL_IPPROTO_TCP_UDP)
{
/* insert TCP rule*/
flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_TCP;
memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
IPACMDBG("Filter rule attrib mask: 0x%x\n",
m_pFilteringTable->rules[0].rule.attrib.attrib_mask);
if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
{
IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
free(m_pFilteringTable);
return IPACM_FAILURE;
}
else
{
/* save v4 firewall filter rule handler */
IPACMDBG("flt rule hdl0=0x%x, status=0x%x\n",
m_pFilteringTable->rules[rule_v4].flt_rule_hdl,
m_pFilteringTable->rules[rule_v4].status);
firewall_hdl_v4[rule_v4] = m_pFilteringTable->rules[0].flt_rule_hdl;
num_firewall_v4++;
rule_v4++;
}
/* insert UDP rule*/
flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_UDP;
memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
IPACMDBG("Filter rule attrib mask: 0x%x\n",
m_pFilteringTable->rules[0].rule.attrib.attrib_mask);
if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
{
IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
free(m_pFilteringTable);
return IPACM_FAILURE;
}
else
{
/* save v4 firewall filter rule handler */
IPACMDBG("flt rule hdl0=0x%x, status=0x%x\n",
m_pFilteringTable->rules[rule_v4].flt_rule_hdl,
m_pFilteringTable->rules[rule_v4].status);
firewall_hdl_v4[rule_v4] = m_pFilteringTable->rules[0].flt_rule_hdl;
num_firewall_v4++;
rule_v4++;
}
}
else
{
memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
IPACMDBG("Filter rule attrib mask: 0x%x\n",
m_pFilteringTable->rules[0].rule.attrib.attrib_mask);
if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
{
IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
free(m_pFilteringTable);
return IPACM_FAILURE;
}
else
{
/* save v4 firewall filter rule handler */
IPACMDBG("flt rule hdl0=0x%x, status=0x%x\n",
m_pFilteringTable->rules[rule_v4].flt_rule_hdl,
m_pFilteringTable->rules[rule_v4].status);
firewall_hdl_v4[rule_v4] = m_pFilteringTable->rules[0].flt_rule_hdl;
num_firewall_v4++;
rule_v4++;
}
}
}
} /* end of firewall ipv4 filter rule add for loop*/
}
/* configure default filter rule */
memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
flt_rule_entry.flt_rule_hdl = -1;
flt_rule_entry.status = -1;
/* firewall disable, all traffic are allowed */
if(firewall_config.firewall_enable == true)
{
flt_rule_entry.at_rear = true;
/* default action for v4 is go DST_NAT unless user set to exception*/
if(firewall_config.rule_action_accept == true)
{
flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
}
else
{
flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
}
}
else
{
flt_rule_entry.at_rear = true;
flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
}
flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
memcpy(&flt_rule_entry.rule.attrib,
&rx_prop->rx[0].attrib,
sizeof(struct ipa_rule_attrib));
flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000;
flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000;
memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
IPACMDBG("Filter rule attrib mask: 0x%x\n",
m_pFilteringTable->rules[0].rule.attrib.attrib_mask);
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 */
dft_wan_fl_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl;
free(m_pFilteringTable);
}
}
else
{
if (rule_v6 == 0)
{
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)
{
IPACMERR("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;
memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v6)) //rt_tbl_wan_v6 rt_tbl_v6
{
IPACMERR("m_routing.GetRoutingTable(rt_tbl_wan_v6) Failed.\n");
free(m_pFilteringTable);
return IPACM_FAILURE;
}
flt_rule_entry.flt_rule_hdl = -1;
flt_rule_entry.status = -1;
flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl;
/* firewall disable, all traffic are allowed */
if(firewall_config.firewall_enable == true)
{
flt_rule_entry.at_rear = true;
/* default action for v6 is PASS_TO_ROUTE unless user set to exception*/
if(firewall_config.rule_action_accept == true)
{
flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
}
else
{
flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
}
}
else
{
flt_rule_entry.at_rear = true;
flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
}
memcpy(&flt_rule_entry.rule.attrib,
&rx_prop->rx[0].attrib,
sizeof(struct ipa_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 rules, 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_wan_fl_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl;
free(m_pFilteringTable);
}
else
{
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)
{
IPACMERR("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_wan_v6))
{
IPACMERR("m_routing.GetRoutingTable(rt_tbl_wan_v6) Failed.\n");
free(m_pFilteringTable);
return IPACM_FAILURE;
}
if(firewall_config.firewall_enable == true)
{
rule_v6 = 0;
for (i = 0; i < firewall_config.num_extd_firewall_entries; i++)
{
if (firewall_config.extd_firewall_entries[i].ip_vsn == 6)
{
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;
/* matched rules for v6 go PASS_TO_ROUTE */
if(firewall_config.rule_action_accept == true)
{
flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
}
else
{
flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
}
flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl;
memcpy(&flt_rule_entry.rule.attrib,
&firewall_config.extd_firewall_entries[i].attrib,
sizeof(struct ipa_rule_attrib));
flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask;
flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask;
flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data;
/* check if the rule is define as TCP/UDP */
if (firewall_config.extd_firewall_entries[i].attrib.u.v6.next_hdr == IPACM_FIREWALL_IPPROTO_TCP_UDP)
{
/* insert TCP rule*/
flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP;
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 rules, aborting...\n");
free(m_pFilteringTable);
return IPACM_FAILURE;
}
else
{
/* save v4 firewall filter rule handler */
IPACMDBG("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
firewall_hdl_v6[rule_v6] = m_pFilteringTable->rules[0].flt_rule_hdl;
num_firewall_v6++;
rule_v6++;
}
/* insert UDP rule*/
flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_UDP;
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 rules, aborting...\n");
free(m_pFilteringTable);
return IPACM_FAILURE;
}
else
{
/* save v6 firewall filter rule handler */
IPACMDBG("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
firewall_hdl_v6[rule_v6] = m_pFilteringTable->rules[0].flt_rule_hdl;
num_firewall_v6++;
rule_v6++;
}
}
else
{
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 rules, aborting...\n");
free(m_pFilteringTable);
return IPACM_FAILURE;
}
else
{
/* save v6 firewall filter rule handler */
IPACMDBG("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
firewall_hdl_v6[rule_v6] = m_pFilteringTable->rules[0].flt_rule_hdl;
num_firewall_v6++;
rule_v6++;
}
}
}
} /* end of firewall ipv6 filter rule add for loop*/
}
/* setup default wan filter rule */
memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
flt_rule_entry.flt_rule_hdl = -1;
flt_rule_entry.status = -1;
flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl;
/* firewall disable, all traffic are allowed */
if(firewall_config.firewall_enable == true)
{
flt_rule_entry.at_rear = true;
/* default action for v6 is PASS_TO_ROUTE unless user set to exception*/
if(firewall_config.rule_action_accept == true)
{
flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
}
else
{
flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
}
}
else
{
flt_rule_entry.at_rear = true;
flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
}
memcpy(&flt_rule_entry.rule.attrib,
&rx_prop->rx[0].attrib,
sizeof(struct ipa_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 rules, 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_wan_fl_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl;
free(m_pFilteringTable);
}
}
return IPACM_SUCCESS;
}
/* configure the initial firewall filter rules */
int IPACM_Wan::config_dft_firewall_rules_ex(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype)
{
struct ipa_flt_rule_add flt_rule_entry;
int i;
int num_rules = 0, original_num_rules = 0;
ipa_ioc_get_rt_tbl_indx rt_tbl_idx;
ipa_ioc_generate_flt_eq flt_eq;
int pos = rule_offset;
IPACMDBG("ip-family: %d; \n", iptype);
if (rx_prop == NULL)
{
IPACMDBG("No rx properties registered for iface %s\n", dev_name);
return IPACM_SUCCESS;
}
if(rules == NULL || rule_offset < 0)
{
IPACMERR("No filtering table is available.\n");
return IPACM_FAILURE;
}
/* default firewall is disable and the rule action is drop */
memset(&firewall_config, 0, sizeof(firewall_config));
strncpy(firewall_config.firewall_config_file, "/etc/mobileap_firewall.xml", sizeof(firewall_config.firewall_config_file));
if (firewall_config.firewall_config_file)
{
IPACMDBG("Firewall XML file is %s \n", firewall_config.firewall_config_file);
if (IPACM_SUCCESS == IPACM_read_firewall_xml(firewall_config.firewall_config_file, &firewall_config))
{
IPACMDBG("QCMAP Firewall XML read OK \n");
}
else
{
IPACMERR("QCMAP Firewall XML read failed, no that file, use default configuration \n");
}
}
else
{
IPACMERR("No firewall xml mentioned \n");
return IPACM_FAILURE;
}
if (iptype == IPA_IP_v4)
{
original_num_rules = IPACM_Wan::num_v4_flt_rule;
if(firewall_config.firewall_enable == true)
{
for (i = 0; i < firewall_config.num_extd_firewall_entries; i++)
{
if (firewall_config.extd_firewall_entries[i].ip_vsn == 4)
{
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.retain_hdr = 1;
flt_rule_entry.rule.to_uc = 0;
flt_rule_entry.rule.eq_attrib_type = 1;
/* Accept v4 matched rules*/
if(firewall_config.rule_action_accept == true)
{
flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
}
else
{
flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
}
memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
rt_tbl_idx.ip = iptype;
if(flt_rule_entry.rule.action == IPA_PASS_TO_ROUTING)
{
strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
}
else /*pass to dst nat*/
{
strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, IPA_RESOURCE_NAME_MAX);
}
if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
{
IPACMERR("Failed to get routing table index from name\n");
return IPACM_FAILURE;
}
flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
IPACMDBG("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
memcpy(&flt_rule_entry.rule.attrib,
&firewall_config.extd_firewall_entries[i].attrib,
sizeof(struct ipa_rule_attrib));
flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask;
flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask;
flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data;
change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib);
/* check if the rule is define as TCP_UDP, split into 2 rules, 1 for TCP and 1 UDP */
if (firewall_config.extd_firewall_entries[i].attrib.u.v4.protocol == IPACM_FIREWALL_IPPROTO_TCP_UDP)
{
/* insert TCP rule*/
flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_TCP;
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
return IPACM_FAILURE;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
IPACMDBG("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask);
pos++;
num_firewall_v4++;
IPACM_Wan::num_v4_flt_rule++;
/* insert UDP rule*/
flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_UDP;
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
return IPACM_FAILURE;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
IPACMDBG("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask);
pos++;
num_firewall_v4++;
IPACM_Wan::num_v4_flt_rule++;
}
else
{
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
return IPACM_FAILURE;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
IPACMDBG("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask);
pos++;
num_firewall_v4++;
IPACM_Wan::num_v4_flt_rule++;
}
}
} /* end of firewall ipv4 filter rule add for loop*/
}
/* configure default filter rule */
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.retain_hdr = 1;
flt_rule_entry.rule.to_uc = 0;
flt_rule_entry.rule.eq_attrib_type = 1;
/* firewall disable, all traffic are allowed */
if(firewall_config.firewall_enable == true)
{
/* default action for v4 is go DST_NAT unless user set to exception*/
if(firewall_config.rule_action_accept == true)
{
flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
}
else
{
flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
}
}
else
{
flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
}
memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
rt_tbl_idx.ip = iptype;
if(flt_rule_entry.rule.action == IPA_PASS_TO_ROUTING)
{
strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
}
else /*pass to dst nat*/
{
strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, IPA_RESOURCE_NAME_MAX);
}
if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
{
IPACMERR("Failed to get routing table index from name\n");
return IPACM_FAILURE;
}
flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
IPACMDBG("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
memcpy(&flt_rule_entry.rule.attrib,
&rx_prop->rx[0].attrib,
sizeof(struct ipa_rule_attrib));
flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000;
flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000;
change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib);
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
return IPACM_FAILURE;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
IPACMDBG("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask);
pos++;
num_firewall_v4++;
IPACM_Wan::num_v4_flt_rule++;
num_rules = IPACM_Wan::num_v4_flt_rule - original_num_rules;
}
else
{
original_num_rules = IPACM_Wan::num_v6_flt_rule;
if(firewall_config.firewall_enable == true)
{
for (i = 0; i < firewall_config.num_extd_firewall_entries; i++)
{
if (firewall_config.extd_firewall_entries[i].ip_vsn == 6)
{
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.retain_hdr = 1;
flt_rule_entry.rule.to_uc = 0;
flt_rule_entry.rule.eq_attrib_type = 1;
flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
rt_tbl_idx.ip = iptype;
/* matched rules for v6 go PASS_TO_ROUTE */
if(firewall_config.rule_action_accept == true)
{
strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX);
}
else
{
strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
}
if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
{
IPACMERR("Failed to get routing table index from name\n");
return IPACM_FAILURE;
}
flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
IPACMDBG("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
memcpy(&flt_rule_entry.rule.attrib,
&firewall_config.extd_firewall_entries[i].attrib,
sizeof(struct ipa_rule_attrib));
flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask;
flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask;
flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data;
change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
/* check if the rule is define as TCP/UDP */
if (firewall_config.extd_firewall_entries[i].attrib.u.v6.next_hdr == IPACM_FIREWALL_IPPROTO_TCP_UDP)
{
/* insert TCP rule*/
flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP;
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
return IPACM_FAILURE;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
pos++;
num_firewall_v6++;
IPACM_Wan::num_v6_flt_rule++;
/* insert UDP rule*/
flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_UDP;
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
return IPACM_FAILURE;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
pos++;
num_firewall_v6++;
IPACM_Wan::num_v6_flt_rule++;
}
else
{
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
return IPACM_FAILURE;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
pos++;
num_firewall_v6++;
IPACM_Wan::num_v6_flt_rule++;
}
}
} /* end of firewall ipv6 filter rule add for loop*/
}
/* setup default wan filter rule */
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.retain_hdr = 1;
flt_rule_entry.rule.to_uc = 0;
flt_rule_entry.rule.eq_attrib_type = 1;
flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
rt_tbl_idx.ip = iptype;
/* firewall disable, all traffic are allowed */
if(firewall_config.firewall_enable == true)
{
/* default action for v6 is PASS_TO_ROUTE unless user set to exception*/
if(firewall_config.rule_action_accept == true)
{
strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
}
else
{
strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX);
}
}
else
{
strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX);
}
if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
{
IPACMERR("Failed to get routing table index from name\n");
return IPACM_FAILURE;
}
flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
IPACMDBG("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
memcpy(&flt_rule_entry.rule.attrib,
&rx_prop->rx[1].attrib,
sizeof(struct ipa_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;
change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
return IPACM_FAILURE;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
pos++;
num_firewall_v6++;
IPACM_Wan::num_v6_flt_rule++;
num_rules = IPACM_Wan::num_v6_flt_rule - original_num_rules;
}
IPACMDBG("Constructed %d firewall rules for ip type %d\n", num_rules, iptype);
return IPACM_SUCCESS;
}
int IPACM_Wan::init_fl_rule_ex(ipa_ip_type iptype)
{
int res = IPACM_SUCCESS;
char *dev_wlan0="wlan0";
char *dev_wlan1="wlan1";
char *dev_ecm0="ecm0";
/* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/
if (iptype == IPA_IP_v4)
{
if ((ip_type == IPA_IP_v4) || (ip_type == IPA_IP_MAX))
{
IPACMDBG(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
return res;
}
if (ip_type == IPA_IP_v6)
{
ip_type = IPA_IP_MAX;
}
else
{
ip_type = IPA_IP_v4;
}
IPACMDBG(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
}
else
{
if ((ip_type == IPA_IP_v6) || (ip_type == IPA_IP_MAX))
{
IPACMDBG(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
return res;
}
if (ip_type == IPA_IP_v4)
{
ip_type = IPA_IP_MAX;
}
else
{
ip_type = IPA_IP_v6;
}
IPACMDBG(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
}
/* ADD corresponding ipa_rm_resource_name of RX-endpoint before adding all IPV4V6 FT-rules */
if(rx_prop != NULL)
{
IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe],false);
IPACMDBG(" add producer dependency from %s with registered rx-prop\n", dev_name);
}
else
{
/* only wlan may take software-path, not register Rx-property*/
if(strcmp(dev_name,dev_wlan0) == 0 || strcmp(dev_name,dev_wlan1) == 0)
{
IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_HSIC_PROD,true);
IPACMDBG(" add producer dependency from %s without registered rx-prop \n", dev_name);
}
if(strcmp(dev_name,dev_ecm0) == 0)
{
IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_USB_PROD,true);
IPACMDBG(" add producer dependency from %s without registered rx-prop \n", dev_name);
}
}
if(iptype == IPA_IP_v4)
{
add_dft_filtering_rule(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4);
}
else if(iptype == IPA_IP_v6)
{
add_dft_filtering_rule(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6);
}
else
{
IPACMERR("IP type is not expected.\n");
res = IPACM_FAILURE;
goto fail;
}
install_wan_filtering_rule();
fail:
return res;
}
int IPACM_Wan::add_icmp_alg_rules(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype)
{
int res = IPACM_SUCCESS, i, original_num_rules = 0, num_rules = 0;
struct ipa_flt_rule_add flt_rule_entry;
IPACM_Config* ipacm_config = IPACM_Iface::ipacmcfg;
ipa_ioc_generate_flt_eq flt_eq;
ipa_ioc_get_rt_tbl_indx rt_tbl_idx;
if(rules == NULL || rule_offset < 0)
{
IPACMERR("No filtering table is available.\n");
return IPACM_FAILURE;
}
if(iptype == IPA_IP_v4)
{
original_num_rules = IPACM_Wan::num_v4_flt_rule;
memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
rt_tbl_idx.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
{
IPACMERR("Failed to get routing table index from name\n");
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("WAN DL routing table %s has index %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, rt_tbl_idx.idx);
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.retain_hdr = 1;
flt_rule_entry.rule.to_uc = 0;
flt_rule_entry.rule.eq_attrib_type = 1;
flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
/* Configuring ICMP filtering rule */
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_PROTOCOL;
flt_rule_entry.rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP;
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
res = IPACM_FAILURE;
goto fail;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
IPACM_Wan::num_v4_flt_rule++;
/* Configure ALG filtering rules */
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_SRC_PORT;
flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
for(i = 0; i < ipacm_config->ipa_num_alg_ports; i++)
{
flt_rule_entry.rule.attrib.src_port = ipacm_config->alg_table[i].port;
flt_rule_entry.rule.attrib.u.v4.protocol = ipacm_config->alg_table[i].protocol;
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
res = IPACM_FAILURE;
goto fail;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[rule_offset + 1 + i]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
IPACM_Wan::num_v4_flt_rule++;
}
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_PORT;
flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
for(i = 0; i < ipacm_config->ipa_num_alg_ports; i++)
{
flt_rule_entry.rule.attrib.dst_port = ipacm_config->alg_table[i].port;
flt_rule_entry.rule.attrib.u.v4.protocol = ipacm_config->alg_table[i].protocol;
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
res = IPACM_FAILURE;
goto fail;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[rule_offset + ipacm_config->ipa_num_alg_ports + 1 + i]),
&flt_rule_entry,
sizeof(struct ipa_flt_rule_add));
IPACM_Wan::num_v4_flt_rule++;
}
num_rules = IPACM_Wan::num_v4_flt_rule - original_num_rules;
}
else /* IPv6 case */
{
original_num_rules = IPACM_Wan::num_v6_flt_rule;
memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
rt_tbl_idx.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
{
IPACMERR("Failed to get routing table index from name\n");
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("WAN DL routing table %s has index %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, rt_tbl_idx.idx);
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.retain_hdr = 1;
flt_rule_entry.rule.to_uc = 0;
flt_rule_entry.rule.eq_attrib_type = 1;
flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
/* Configuring ICMP filtering rule */
memcpy(&flt_rule_entry.rule.attrib,
&rx_prop->rx[1].attrib,
sizeof(flt_rule_entry.rule.attrib));
flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6;
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
res = IPACM_FAILURE;
goto fail;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
IPACM_Wan::num_v6_flt_rule++;
num_rules = IPACM_Wan::num_v6_flt_rule - original_num_rules;
}
fail:
IPACMDBG("Constructed %d ICMP/ALG rules for ip type %d\n", num_rules, iptype);
return res;
}
int IPACM_Wan::query_ext_prop()
{
int fd, ret = IPACM_SUCCESS, cnt;
if (iface_query->num_ext_props > 0)
{
fd = open(IPA_DEVICE_NAME, O_RDWR);
IPACMDBG("iface query-property \n");
if (0 == fd)
{
IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
return IPACM_FAILURE;
}
ext_prop = (struct ipa_ioc_query_intf_ext_props *)
calloc(1, sizeof(struct ipa_ioc_query_intf_ext_props) +
iface_query->num_ext_props * sizeof(struct ipa_ioc_ext_intf_prop));
if(ext_prop == NULL)
{
IPACMERR("Unable to allocate memory.\n");
return IPACM_FAILURE;
}
memcpy(ext_prop->name, dev_name,
sizeof(dev_name));
ext_prop->num_ext_props = iface_query->num_ext_props;
IPACMDBG("Query extended property for iface %s\n", ext_prop->name);
ret = ioctl(fd, IPA_IOC_QUERY_INTF_EXT_PROPS, ext_prop);
if (ret < 0)
{
IPACMERR("ioctl IPA_IOC_QUERY_INTF_EXT_PROPS failed\n");
/* ext_prop memory will free when iface-down*/
free(ext_prop);
return ret;
}
IPACMDBG("Wan interface has %d tx props, %d rx props and %d ext props\n", iface_query->num_tx_props, iface_query->num_rx_props, iface_query->num_ext_props);
for (cnt = 0; cnt < ext_prop->num_ext_props; cnt++)
{
IPACMDBG("Ex(%d): ip-type: %d, mux_id: %d, flt_action: %d\n, rt_tbl_idx: %d, flt_hdr: %d \n",
cnt, ext_prop->ext[cnt].ip, ext_prop->ext[cnt].mux_id, ext_prop->ext[cnt].action, ext_prop->ext[cnt].rt_tbl_idx, ext_prop->ext[cnt].filter_hdl);
}
IPACM_Iface::ipacmcfg->SetQmapId(ext_prop->ext[0].mux_id);
if(IPACM_Wan::is_ext_prop_set == false)
{
IPACM_Iface::ipacmcfg->SetExtProp(ext_prop);
IPACM_Wan::is_ext_prop_set = true;
}
free(ext_prop);
}
return IPACM_SUCCESS;
}
int IPACM_Wan::config_wan_firewall_rule(ipa_ip_type iptype)
{
int res = IPACM_SUCCESS;
IPACMDBG("Configure WAN DL firewall rules.\n");
if(iptype == IPA_IP_v4)
{
if(IPACM_FAILURE == add_icmp_alg_rules(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4))
{
IPACMERR("Failed to add ICMP and ALG port filtering rules.\n");
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("Succeded in constructing ICMP/ALG rules for ip type %d\n", iptype);
if(IPACM_FAILURE == config_dft_firewall_rules_ex(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4))
{
IPACMERR("Failed to add firewall filtering rules.\n");
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("Succeded in constructing firewall rules for ip type %d\n", iptype);
}
else if(iptype == IPA_IP_v6)
{
if(IPACM_FAILURE == add_icmp_alg_rules(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6))
{
IPACMERR("Failed to add ICMP and ALG port filtering rules.\n");
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("Succeded in constructing ICMP/ALG rules for ip type %d\n", iptype);
if(IPACM_FAILURE == config_dft_firewall_rules_ex(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6))
{
IPACMERR("Failed to add firewall filtering rules.\n");
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("Succeded in constructing firewall rules for ip type %d\n", iptype);
}
else
{
IPACMERR("IP type is not expected.\n");
return IPACM_FAILURE;
}
fail:
return res;
}
int IPACM_Wan::add_dft_filtering_rule(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype)
{
struct ipa_ioc_get_rt_tbl_indx rt_tbl_idx;
struct ipa_flt_rule_add flt_rule_entry;
struct ipa_ioc_generate_flt_eq flt_eq;
int res = IPACM_SUCCESS;
if(rules == NULL)
{
IPACMERR("No filtering table available.\n");
return IPACM_FAILURE;
}
if(rx_prop == NULL)
{
IPACMERR("No tx property.\n");
return IPACM_FAILURE;
}
if (iptype == IPA_IP_v4)
{
memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
rt_tbl_idx.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
{
IPACMERR("Failed to get routing table index from name\n");
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
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.retain_hdr = 1;
flt_rule_entry.rule.to_uc = 0;
flt_rule_entry.rule.eq_attrib_type = 1;
flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
IPACMDBG("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
/* Configuring Multicast Filtering Rule */
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 = 0xF0000000;
flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000;
change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib);
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
res = IPACM_FAILURE;
goto fail;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
/* Configuring Broadcast Filtering Rule */
flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF;
change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib);
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
res = IPACM_FAILURE;
goto fail;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[rule_offset + 1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
IPACM_Wan::num_v4_flt_rule += IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4;
IPACMDBG("Constructed %d default filtering rules for ip type %d\n", IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4, iptype);
}
else /*insert rules for ipv6*/
{
memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
strncpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
rt_tbl_idx.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx))
{
IPACMERR("Failed to get routing table index from name\n");
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx);
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.retain_hdr = 1;
flt_rule_entry.rule.to_uc = 0;
flt_rule_entry.rule.eq_attrib_type = 1;
flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
/* Configuring Multicast Filtering Rule */
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] = 0xFF000000;
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] = 0xFF000000;
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;
change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
res = IPACM_FAILURE;
goto fail;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
/* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFC00000;
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] = 0xFE800000;
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;
change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
res = IPACM_FAILURE;
goto fail;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[rule_offset + 1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
/* Configuring fec0::/10 Reserved by IETF Filtering Rule */
flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFC00000;
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] = 0xFEC00000;
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;
change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib);
memset(&flt_eq, 0, sizeof(flt_eq));
memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
flt_eq.ip = iptype;
if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
{
IPACMERR("Failed to get eq_attrib\n");
res = IPACM_FAILURE;
goto fail;
}
memcpy(&flt_rule_entry.rule.eq_attrib,
&flt_eq.eq_attrib,
sizeof(flt_rule_entry.rule.eq_attrib));
memcpy(&(rules[rule_offset + 2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
IPACM_Wan::num_v6_flt_rule += IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6;
IPACMDBG("Constructed %d default filtering rules for ip type %d\n", IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6, iptype);
}
fail:
return res;
}
int IPACM_Wan::del_wan_firewall_rule(ipa_ip_type iptype)
{
if(iptype == IPA_IP_v4)
{
IPACM_Wan::num_v4_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4;
memset(&IPACM_Wan::flt_rule_v4[IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4], 0,
(IPA_MAX_FLT_RULE - IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4) * sizeof(struct ipa_flt_rule_add));
}
else if(iptype == IPA_IP_v6)
{
IPACM_Wan::num_v6_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6;
memset(&IPACM_Wan::flt_rule_v6[IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6], 0,
(IPA_MAX_FLT_RULE - IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6) * sizeof(struct ipa_flt_rule_add));
}
else
{
IPACMERR("IP type is not expected.\n");
return IPACM_FAILURE;
}
return IPACM_SUCCESS;
}
/*for STA mode: clean firewall filter rules */
int IPACM_Wan::del_dft_firewall_rules(ipa_ip_type iptype)
{
/* free v4 firewall filter rule */
if (rx_prop == NULL)
{
IPACMDBG("No rx properties registered for iface %s\n", dev_name);
return IPACM_SUCCESS;
}
if ((iptype == IPA_IP_v4) && (active_v4 == true))
{
if (num_firewall_v4 > IPACM_MAX_FIREWALL_ENTRIES)
{
IPACMERR("the number of v4 firewall entries overflow, aborting...\n");
return IPACM_FAILURE;
}
if (num_firewall_v4 != 0)
{
if (m_filtering.DeleteFilteringHdls(firewall_hdl_v4,
IPA_IP_v4, num_firewall_v4) == false)
{
IPACMERR("Error Deleting Filtering rules, aborting...\n");
return IPACM_FAILURE;
}
}
else
{
IPACMDBG("No ipv4 firewall rules, no need deleted\n");
}
if (m_filtering.DeleteFilteringHdls(dft_wan_fl_hdl,
IPA_IP_v4, 1) == false)
{
IPACMERR("Error Deleting Filtering rules, aborting...\n");
return IPACM_FAILURE;
}
num_firewall_v4 = 0;
}
/* free v6 firewall filter rule */
if ((iptype == IPA_IP_v6) && (active_v6 == true))
{
if (num_firewall_v6 > IPACM_MAX_FIREWALL_ENTRIES)
{
IPACMERR("the number of v6 firewall entries overflow, aborting...\n");
return IPACM_FAILURE;
}
if (num_firewall_v6 != 0)
{
if (m_filtering.DeleteFilteringHdls(firewall_hdl_v6,
IPA_IP_v6, num_firewall_v6) == false)
{
IPACMERR("Error Deleting Filtering rules, aborting...\n");
return IPACM_FAILURE;
}
}
else
{
IPACMDBG("No ipv6 firewall rules, no need deleted\n");
}
if (m_filtering.DeleteFilteringHdls(&dft_wan_fl_hdl[1],
IPA_IP_v6, 1) == false)
{
IPACMERR("Error Deleting Filtering rules, aborting...\n");
return IPACM_FAILURE;
}
num_firewall_v6 = 0;
}
return IPACM_SUCCESS;
}
/* for STA mode: wan default route/filter rule delete */
int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype)
{
uint32_t tx_index;
ipacm_cmd_q_data evt_data;
IPACMDBG("got handle_route_del_evt with ip-family:%d \n", iptype);
if(tx_prop == NULL)
{
IPACMDBG("No tx properties, ignore delete default route setting\n");
return IPACM_SUCCESS;
}
if (((iptype == IPA_IP_v4) && (active_v4 == true)) ||
((iptype == IPA_IP_v6) && (active_v6 == true)))
{
/* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */
IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
{
if(iptype != tx_prop->tx[tx_index].ip)
{
IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d, no RT-rule deleted\n",
tx_index, tx_prop->tx[tx_index].ip,iptype);
continue;
}
if (iptype == IPA_IP_v4)
{
IPACMDBG("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n", tx_index, tx_prop->tx[tx_index].ip,iptype);
if (m_routing.DeleteRoutingHdl(wan_route_rule_v4_hdl[tx_index], IPA_IP_v4) == false)
{
IPACMDBG("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v4, wan_route_rule_v4_hdl[tx_index], tx_index);
return IPACM_FAILURE;
}
}
else
{
IPACMDBG("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n", tx_index, tx_prop->tx[tx_index].ip,iptype);
if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl[tx_index], IPA_IP_v6) == false)
{
IPACMDBG("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v6, wan_route_rule_v6_hdl[tx_index], tx_index);
return IPACM_FAILURE;
}
}
}
/* Delete the default wan route*/
if (iptype == IPA_IP_v6)
{
IPACMDBG("ip-type %d: default v6 wan RT-rule deleted\n",iptype);
if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl_a5[0], IPA_IP_v6) == false)
{
IPACMDBG("IP-family:%d, Routing rule(hdl:0x%x) deletion failed!\n",IPA_IP_v6,wan_route_rule_v6_hdl_a5[0]);
return IPACM_FAILURE;
}
}
ipacm_event_iface_up *wandown_data;
wandown_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up));
if (wandown_data == NULL)
{
IPACMERR("Unable to allocate memory\n");
return IPACM_FAILURE;
}
memset(wandown_data, 0, sizeof(ipacm_event_iface_up));
if (iptype == IPA_IP_v4)
{
wandown_data->ipv4_addr = wan_v4_addr;
if (m_is_sta_mode!=0)
{
wandown_data->is_sta = true;
}
else
{
wandown_data->is_sta = false;
}
evt_data.event = IPA_HANDLE_WAN_DOWN;
evt_data.evt_data = (void *)wandown_data;
/* Insert IPA_HANDLE_WAN_DOWN to command queue */
IPACMDBG("posting IPA_HANDLE_WAN_DOWN for IPv4 \n");
IPACM_EvtDispatcher::PostEvt(&evt_data);
IPACMDBG("setup wan_up/active_v4= false \n");
IPACM_Wan::wan_up = false;
active_v4 = false;
}
else
{
if (m_is_sta_mode!=0)
{
wandown_data->is_sta = true;
}
else
{
wandown_data->is_sta = false;
}
evt_data.event = IPA_HANDLE_WAN_DOWN_V6;
evt_data.evt_data = (void *)wandown_data;
/* Insert IPA_HANDLE_WAN_DOWN to command queue */
IPACMDBG("posting IPA_HANDLE_WAN_DOWN for IPv6 \n");
IPACM_EvtDispatcher::PostEvt(&evt_data);
IPACMDBG("setup wan_up_v6/active_v6= false \n");
IPACM_Wan::wan_up_v6 = false;
active_v6 = false;
}
}
else
{
IPACMDBG(" The default WAN routing rules are deleted already \n");
}
return IPACM_SUCCESS;
}
int IPACM_Wan::handle_route_del_evt_ex(ipa_ip_type iptype)
{
ipacm_cmd_q_data evt_data;
IPACMDBG("got handle_route_del_evt_ex with ip-family:%d \n", iptype);
if(tx_prop == NULL)
{
IPACMDBG("No tx properties, ignore delete default route setting\n");
return IPACM_SUCCESS;
}
if (((iptype == IPA_IP_v4) && (active_v4 == true)) ||
((iptype == IPA_IP_v6) && (active_v6 == true)))
{
/* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */
IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
/* Delete the default route*/
if (iptype == IPA_IP_v6)
{
IPACMDBG("ip-type %d: default v6 wan RT-rule deleted\n",iptype);
if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl_a5[0], IPA_IP_v6) == false)
{
IPACMDBG("IP-family:%d, Routing rule(hdl:0x%x) deletion failed!\n",IPA_IP_v6,wan_route_rule_v6_hdl_a5[0]);
return IPACM_FAILURE;
}
}
ipacm_event_iface_up *wandown_data;
wandown_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up));
if (wandown_data == NULL)
{
IPACMERR("Unable to allocate memory\n");
return IPACM_FAILURE;
}
memset(wandown_data, 0, sizeof(ipacm_event_iface_up));
if (iptype == IPA_IP_v4)
{
wandown_data->ipv4_addr = wan_v4_addr;
if (m_is_sta_mode!=0)
{
wandown_data->is_sta = true;
}
else
{
wandown_data->is_sta = false;
}
evt_data.event = IPA_HANDLE_WAN_DOWN;
evt_data.evt_data = (void *)wandown_data;
/* Insert IPA_HANDLE_WAN_DOWN to command queue */
IPACMDBG("posting IPA_HANDLE_WAN_DOWN for IPv4 with address: 0x%x\n", wan_v4_addr);
IPACM_EvtDispatcher::PostEvt(&evt_data);
IPACMDBG("setup wan_up/active_v4= false \n");
IPACM_Wan::wan_up = false;
active_v4 = false;
}
else
{
if (m_is_sta_mode!=0)
{
wandown_data->is_sta = true;
}
else
{
wandown_data->is_sta = false;
}
evt_data.event = IPA_HANDLE_WAN_DOWN_V6;
evt_data.evt_data = (void *)wandown_data;
IPACMDBG("posting IPA_HANDLE_WAN_DOWN_V6 for IPv6 \n");
IPACM_EvtDispatcher::PostEvt(&evt_data);
IPACMDBG("setup wan_up_v6/active_v6= false \n");
IPACM_Wan::wan_up_v6 = false;
active_v6 = false;
}
}
else
{
IPACMDBG(" The default WAN routing rules are deleted already \n");
}
return IPACM_SUCCESS;
}
/*for STA mode: handle wan-iface down event */
int IPACM_Wan::handle_down_evt()
{
int res = IPACM_SUCCESS;
int i;
IPACMDBG(" wan handle_down_evt \n");
/* no iface address up, directly close iface*/
if (ip_type == IPACM_IP_NULL)
{
goto fail;
}
/* make sure default routing rules and firewall rules are deleted*/
if (active_v4)
{
if (rx_prop != NULL)
{
del_dft_firewall_rules(IPA_IP_v4);
}
handle_route_del_evt(IPA_IP_v4);
IPACMDBG("Delete default v4 routing rules\n");
}
if (active_v6)
{
if (rx_prop != NULL)
{
del_dft_firewall_rules(IPA_IP_v6);
}
handle_route_del_evt(IPA_IP_v6);
IPACMDBG("Delete default v6 routing rules\n");
}
/* Delete default v4 RT rule */
if (ip_type != IPA_IP_v6)
{
IPACMDBG("Delete default v4 routing rules\n");
if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
{
IPACMERR("Routing rule deletion failed!\n");
res = IPACM_FAILURE;
goto fail;
}
}
/* delete default v6 RT rule */
if (ip_type != IPA_IP_v4)
{
IPACMDBG("Delete default v6 routing rules\n");
/* May have multiple ipv6 iface-routing 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 v6 RT rules\n ");
}
/* check software routing fl rule hdl */
if (softwarerouting_act == true)
{
handle_software_routing_disable();
}
/* free filter rule handlers */
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 Delete Filtering rules, aborting...\n");
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("finished delete default v4 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) == false)
{
IPACMERR("ErrorDeleting Filtering rule, aborting...\n");
res = IPACM_FAILURE;
goto fail;
}
IPACMDBG("finished delete default v6 filtering rules\n ");
}
/* delete the complete header for STA mode*/
if((header_set_v4 == true) || (header_set_v6 == true))
{
if (m_header.DeleteHeaderHdl(hdr_hdl_sta_v4) == false)
{
IPACMERR("ErrorDeleting STA header for v4, aborting...\n");
res = IPACM_FAILURE;
goto fail;
}
if (m_header.DeleteHeaderHdl(hdr_hdl_sta_v6) == false)
{
IPACMERR("ErrorDeleting STA header for v6, aborting...\n");
res = IPACM_FAILURE;
goto fail;
}
}
fail:
if (tx_prop != NULL)
{
free(tx_prop);
}
if (rx_prop != NULL)
{
free(rx_prop);
}
if (iface_query != NULL)
{
free(iface_query);
}
if (wan_route_rule_v4_hdl != NULL)
{
free(wan_route_rule_v4_hdl);
}
if (wan_route_rule_v6_hdl != NULL)
{
free(wan_route_rule_v6_hdl);
}
if (wan_route_rule_v6_hdl_a5 != NULL)
{
free(wan_route_rule_v6_hdl_a5);
}
close(m_fd_ipa);
return res;
}
int IPACM_Wan::handle_down_evt_ex()
{
int res = IPACM_SUCCESS;
int i;
IPACMDBG(" wan handle_down_evt \n");
/* no iface address up, directly close iface*/
if (ip_type == IPACM_IP_NULL)
{
goto fail;
}
if(ip_type == IPA_IP_v4)
{
IPACM_Wan::wan_up = 0;
IPACM_Wan::num_v4_flt_rule = 0;
memset(IPACM_Wan::flt_rule_v4, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
install_wan_filtering_rule();
handle_route_del_evt_ex(IPA_IP_v4);
if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
{
IPACMERR("Routing rule deletion failed!\n");
res = IPACM_FAILURE;
goto fail;
}
}
else if(ip_type == IPA_IP_v6)
{
IPACM_Wan::wan_up_v6 = 0;
IPACM_Wan::num_v6_flt_rule = 0;
memset(IPACM_Wan::flt_rule_v6, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
install_wan_filtering_rule();
handle_route_del_evt_ex(IPA_IP_v6);
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;
}
}
}
else
{
IPACM_Wan::wan_up = 0;
IPACM_Wan::num_v4_flt_rule = 0;
memset(IPACM_Wan::flt_rule_v4, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
handle_route_del_evt_ex(IPA_IP_v4);
IPACM_Wan::wan_up_v6 = 0;
IPACM_Wan::num_v6_flt_rule = 0;
memset(IPACM_Wan::flt_rule_v6, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add));
handle_route_del_evt_ex(IPA_IP_v6);
install_wan_filtering_rule();
if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false)
{
IPACMERR("Routing rule deletion failed!\n");
res = IPACM_FAILURE;
goto fail;
}
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;
}
}
}
/* check software routing fl rule hdl */
if (softwarerouting_act == true)
{
handle_software_routing_disable();
}
/* delete the complete header for STA mode*/
if((header_set_v4 == true) || (header_set_v6 == true))
{
if (m_header.DeleteHeaderHdl(hdr_hdl_sta_v4) == false)
{
IPACMERR("ErrorDeleting STA header for v4, aborting...\n");
res = IPACM_FAILURE;
goto fail;
}
if (m_header.DeleteHeaderHdl(hdr_hdl_sta_v6) == false)
{
IPACMERR("ErrorDeleting STA header for v6, aborting...\n");
res = IPACM_FAILURE;
goto fail;
}
}
fail:
if (tx_prop != NULL)
{
free(tx_prop);
}
if (rx_prop != NULL)
{
free(rx_prop);
}
if (iface_query != NULL)
{
free(iface_query);
}
if (wan_route_rule_v4_hdl != NULL)
{
free(wan_route_rule_v4_hdl);
}
if (wan_route_rule_v6_hdl != NULL)
{
free(wan_route_rule_v6_hdl);
}
if (wan_route_rule_v6_hdl_a5 != NULL)
{
free(wan_route_rule_v6_hdl_a5);
}
close(m_fd_ipa);
return res;
}
int IPACM_Wan::install_wan_filtering_rule()
{
int len, res = IPACM_SUCCESS;
uint8_t mux_id;
ipa_ioc_add_flt_rule *pFilteringTable_v4 = NULL;
ipa_ioc_add_flt_rule *pFilteringTable_v6 = NULL;
mux_id = IPACM_Iface::ipacmcfg->GetQmapId();
if(rx_prop == NULL)
{
IPACMDBG("No rx properties registered for iface %s\n", dev_name);
return IPACM_SUCCESS;
}
if(IPACM_Wan::num_v4_flt_rule > 0)
{
len = sizeof(struct ipa_ioc_add_flt_rule) + IPACM_Wan::num_v4_flt_rule * sizeof(struct ipa_flt_rule_add);
pFilteringTable_v4 = (struct ipa_ioc_add_flt_rule*)malloc(len);
IPACMDBG("Total number of WAN DL filtering rule for IPv4 is %d\n", IPACM_Wan::num_v4_flt_rule);
if (pFilteringTable_v4 == NULL)
{
IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
return IPACM_FAILURE;
}
pFilteringTable_v4->commit = 1;
pFilteringTable_v4->ep = rx_prop->rx[0].src_pipe;
pFilteringTable_v4->global = false;
pFilteringTable_v4->ip = IPA_IP_v4;
pFilteringTable_v4->num_rules = (uint8_t)IPACM_Wan::num_v4_flt_rule;
memcpy(pFilteringTable_v4->rules, IPACM_Wan::flt_rule_v4, IPACM_Wan::num_v4_flt_rule * sizeof(ipa_flt_rule_add));
}
if(IPACM_Wan::num_v6_flt_rule > 0)
{
len = sizeof(struct ipa_ioc_add_flt_rule) + IPACM_Wan::num_v6_flt_rule * sizeof(struct ipa_flt_rule_add);
pFilteringTable_v6 = (struct ipa_ioc_add_flt_rule*)malloc(len);
IPACMDBG("Total number of WAN DL filtering rule for IPv6 is %d\n", IPACM_Wan::num_v6_flt_rule);
if (pFilteringTable_v6 == NULL)
{
IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
free(pFilteringTable_v4);
return IPACM_FAILURE;
}
pFilteringTable_v6->commit = 1;
pFilteringTable_v6->ep = rx_prop->rx[0].src_pipe;
pFilteringTable_v6->global = false;
pFilteringTable_v6->ip = IPA_IP_v6;
pFilteringTable_v6->num_rules = (uint8_t)IPACM_Wan::num_v6_flt_rule;
memcpy(pFilteringTable_v6->rules, IPACM_Wan::flt_rule_v6, IPACM_Wan::num_v6_flt_rule * sizeof(ipa_flt_rule_add));
}
if(false == m_filtering.AddWanDLFilteringRule(pFilteringTable_v4, pFilteringTable_v6, mux_id))
{
IPACMERR("Failed to install WAN DL filtering table.\n");
res = IPACM_FAILURE;
goto fail;
}
fail:
if(pFilteringTable_v4 != NULL)
{
free(pFilteringTable_v4);
}
if(pFilteringTable_v6 != NULL)
{
free(pFilteringTable_v6);
}
return res;
}
void IPACM_Wan::change_to_network_order(ipa_ip_type iptype, ipa_rule_attrib* attrib)
{
if(attrib == NULL)
{
IPACMERR("Attribute pointer is NULL.\n");
return;
}
if(iptype == IPA_IP_v4)
{
attrib->u.v4.src_addr = htonl(attrib->u.v4.src_addr);
attrib->u.v4.src_addr_mask = htonl(attrib->u.v4.src_addr_mask);
attrib->u.v4.dst_addr = htonl(attrib->u.v4.dst_addr);
attrib->u.v4.dst_addr_mask = htonl(attrib->u.v4.dst_addr_mask);
}
else if(iptype == IPA_IP_v6)
{
int i;
for(i=0; i<4; i++)
{
attrib->u.v6.src_addr[i] = htonl(attrib->u.v6.src_addr[i]);
attrib->u.v6.src_addr_mask[i] = htonl(attrib->u.v6.src_addr_mask[i]);
attrib->u.v6.dst_addr[i] = htonl(attrib->u.v6.dst_addr[i]);
attrib->u.v6.dst_addr_mask[i] = htonl(attrib->u.v6.dst_addr_mask[i]);
}
}
else
{
IPACMERR("IP type is not expected: %d\n", iptype);
}
return;
}