Merge 68c5d9a38a6a8bd833321768fe862630fdbc482f on remote branch
Change-Id: I1c1d52b92216fb78f172ebb91d0e41763897b8e8
diff --git a/ipacm/Android.bp b/ipacm/Android.bp
index c6ed74b..fbb69e3 100644
--- a/ipacm/Android.bp
+++ b/ipacm/Android.bp
@@ -70,3 +70,12 @@
src: "src/IPACM_cfg.xml",
}
+
+prebuilt_etc {
+ name: "IPACM_Filter_cfg.xml",
+
+ vendor: true,
+ owner: "ipacm",
+ src: "src/IPACM_Filter_cfg.xml",
+
+}
diff --git a/ipacm/inc/IPACM_Config.h b/ipacm/inc/IPACM_Config.h
index cc89c83..f0f1cf5 100644
--- a/ipacm/inc/IPACM_Config.h
+++ b/ipacm/inc/IPACM_Config.h
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2021, 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
@@ -96,6 +96,9 @@
/* Store private subnet configuration from XML file */
ipa_private_subnet private_subnet_table[IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES];
+ /* Store Filter configuration. */
+ IPACM_filter_conf_t filter_config;
+
/* Store the non nat iface names */
NatIfaces *pNatIfaces;
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index 82e9c6b..20bef93 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2021, 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
@@ -78,6 +78,7 @@
#define IPA_MAX_IFACE_ENTRIES 20
#define IPA_MAX_PRIVATE_SUBNET_ENTRIES 3
#define IPA_MAX_MTU_ENTRIES 3
+#define IPA_MAX_FILTER_CFG_ENTRIES 2
#define IPA_MAX_ALG_ENTRIES 20
#define IPA_MAX_RM_ENTRY 6
@@ -110,6 +111,8 @@
#define LOOPBACK_MASK 0xFF000000
#define LOOPBACK_ADDR 0x7F000000
+#define IPACM_FILTER_CFG_FILE "/data/vendor/ipa/IPACM_Filter_cfg.xml"
+
/*---------------------------------------------------------------------------
Return values indicating error status
---------------------------------------------------------------------------*/
@@ -136,6 +139,7 @@
IPA_CFG_CHANGE_EVENT, /* NULL */
IPA_PRIVATE_SUBNET_CHANGE_EVENT, /* ipacm_event_data_fid */
IPA_FIREWALL_CHANGE_EVENT, /* NULL */
+ IPA_FILTER_CFG_CHANGE_EVENT, /* NULL */
IPA_LINK_UP_EVENT, /* ipacm_event_data_fid */
IPA_LINK_DOWN_EVENT, /* ipacm_event_data_fid */
IPA_USB_LINK_UP_EVENT, /* ipacm_event_data_fid */
diff --git a/ipacm/inc/IPACM_Lan.h b/ipacm/inc/IPACM_Lan.h
index de64be1..735ce6b 100644
--- a/ipacm/inc/IPACM_Lan.h
+++ b/ipacm/inc/IPACM_Lan.h
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2021, 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
@@ -63,6 +63,20 @@
#define PIPE_STATS "%s %s %llu %llu %llu %llu"
#define IPA_PIPE_STATS_FILE_NAME "/data/misc/ipa/tether_stats"
+#define IPA_DOWNSTREAM_TETHER_STATE_FILE_NAME "/data/vendor/ipa/downstream_state"
+/* Max tether interfaces: rndis0/wlan0/wlan1 */
+#define IPA_MAX_TETHER_IFACE_ENTRIES 3
+
+/* Down Stream information. */
+struct ipa_lan_downstream_info
+{
+ /* IPACM interface name */
+ char dev_name[IF_NAME_LEN];
+ /* Down Stream state */
+ bool downstream_state;
+ /* Bool indicating entry in use. */
+ bool entry_in_use;
+};
/* store each lan-iface unicast routing rule and its handler*/
struct ipa_lan_rt_rule
@@ -115,9 +129,17 @@
/* store private-subnet filter rule handlers */
uint32_t private_fl_rule_hdl[IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES];
+ /* store filter cfg rule handles */
+ uint32_t filter_cfg_rule_hdl[IPA_MAX_FILTER_CFG_ENTRIES];
+
+ /* store downstream information */
+ static struct ipa_lan_downstream_info downstream_info[IPA_MAX_TETHER_IFACE_ENTRIES];
+
/* LAN-iface's callback function */
void event_callback(ipa_cm_event_id event, void *data);
+ virtual void store_downstream_state(bool up, enum ipa_ip_type iptype);
+
virtual int handle_wan_up(ipa_ip_type ip_type);
/* configure filter rule for wan_up event*/
@@ -230,6 +252,10 @@
int reset_to_dummy_flt_rule(ipa_ip_type iptype, uint32_t rule_hdl);
+ int handle_filter_cfg_update(ipa_ip_type iptype);
+
+ int add_dummy_filter_cfg_rules(ipa_ip_type iptype);
+
virtual int modify_ipv6_prefix_flt_rule(uint32_t* prefix);
virtual int install_ipv6_prefix_flt_rule(uint32_t* prefix);
diff --git a/ipacm/inc/IPACM_Wan.h b/ipacm/inc/IPACM_Wan.h
index a73ec98..d762430 100644
--- a/ipacm/inc/IPACM_Wan.h
+++ b/ipacm/inc/IPACM_Wan.h
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2021, 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
@@ -63,6 +63,7 @@
#define NETWORK_STATS "%s %llu %llu %llu %llu"
#define IPA_NETWORK_STATS_FILE_NAME "/data/misc/ipa/network_stats"
+#define IPA_OFFLOAD_TETHER_STATE_FILE_NAME "/data/vendor/ipa/offload_state"
typedef struct _wan_client_rt_hdl
{
@@ -640,6 +641,10 @@
int config_dft_firewall_rules_ex(struct ipa_flt_rule_add* rules, int rule_offset,
ipa_ip_type iptype);
+ /* configure dl ack rule if enabled. */
+ int config_filter_dl_ack_rule_ex(struct ipa_flt_rule_add *rules, int rule_offset,
+ ipa_ip_type iptype);
+
/* init filtering rule in wan dl filtering table */
int init_fl_rule_ex(ipa_ip_type iptype);
diff --git a/ipacm/inc/IPACM_Xml.h b/ipacm/inc/IPACM_Xml.h
index c78eefd..77059d3 100644
--- a/ipacm/inc/IPACM_Xml.h
+++ b/ipacm/inc/IPACM_Xml.h
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2021, 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
@@ -65,6 +65,7 @@
/* Max allowed size of the XML file (2 MB) */
#define IPACM_XML_MAX_FILESIZE (2 << 20)
#define IPACM_MAX_FIREWALL_ENTRIES 50
+#define IPACM_MAX_FILTER_CFG_ENTRIES 10
#define IPACM_IPV6_ADDR_LEN 16
/* Defines for clipping space or space & quotes (single, double) */
@@ -113,6 +114,13 @@
#define SRAM_TABLETYPE_TAG "SRAM"
#define HYBRID_TABLETYPE_TAG "HYBRID"
+/* Filter Config Entries */
+#define FilterCfg_TAG "IPACMFilterCfg"
+#define FilterEnabled_TAG "FilteringEnabled"
+#define FilterDLAck_TAG "FilterDLAck"
+#define FilterEntry_TAG "FilterEntry"
+
+
/* FIREWALL Config Entries */
#define Firewall_TAG "Firewall"
#define MobileAPFirewallCfg_TAG "MobileAPFirewallCfg"
@@ -216,7 +224,7 @@
{
IP_V4 = 4,
IP_V6 = 6
-} firewall_ip_version_enum;
+} ip_version_enum;
/*---------------------------------------------------------------------------
Extended FireWall Entry Configuration.
@@ -224,7 +232,7 @@
typedef struct
{
struct ipa_rule_attrib attrib;
- firewall_ip_version_enum ip_vsn;
+ ip_version_enum ip_vsn;
} IPACM_extd_firewall_entry_conf_t;
@@ -245,8 +253,23 @@
bool rule_action_accept;
bool firewall_enable;
} IPACM_firewall_conf_t;
-
+/*---------------------------------------------------------------------------
+ Filter Configuration.
+---------------------------------------------------------------------------*/
+typedef struct
+{
+ struct ipa_rule_attrib attrib;
+ ip_version_enum ip_vsn;
+} IPACM_filter_conf_entry_t;
+
+typedef struct
+{
+ bool filter_enable;
+ bool dl_ack_filter_enable;
+ uint8_t num_filter_cfg_entries;
+ IPACM_filter_conf_entry_t filter_cfg_entries[IPACM_MAX_FILTER_CFG_ENTRIES];
+} IPACM_filter_conf_t;
typedef struct
{
@@ -301,6 +324,14 @@
IPACM_firewall_conf_t *config /* Mobile AP config data */
);
+/* This function reads Filter Cfg XML and store in IPACM Filter Cfg stucture */
+int IPACM_read_filter_cfg_xml
+(
+ char *xml_file, /* Filename and path */
+ IPACM_filter_conf_t *config /* Filter config data */
+);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/ipacm/src/IPACM_Config.cpp b/ipacm/src/IPACM_Config.cpp
index 55b6f43..369c7d4 100644
--- a/ipacm/src/IPACM_Config.cpp
+++ b/ipacm/src/IPACM_Config.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2021, 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
@@ -53,6 +53,7 @@
__stringify(IPA_CFG_CHANGE_EVENT), /* NULL */
__stringify(IPA_PRIVATE_SUBNET_CHANGE_EVENT), /* ipacm_event_data_fid */
__stringify(IPA_FIREWALL_CHANGE_EVENT), /* NULL */
+ __stringify(IPA_FILTER_CFG_CHANGE_EVENT), /* NULL */
__stringify(IPA_LINK_UP_EVENT), /* ipacm_event_data_fid */
__stringify(IPA_LINK_DOWN_EVENT), /* ipacm_event_data_fid */
__stringify(IPA_USB_LINK_UP_EVENT), /* ipacm_event_data_fid */
@@ -349,6 +350,18 @@
goto fail;
}
+ /* default fillter config is disable. */
+ memset(&filter_config, 0, sizeof(filter_config));
+ strlcpy(IPACM_config_file, IPACM_FILTER_CFG_FILE, sizeof(IPACM_config_file));
+ if (IPACM_SUCCESS == IPACM_read_filter_cfg_xml(IPACM_config_file, &filter_config))
+ {
+ IPACMDBG_H("Filter XML read OK \n");
+ }
+ else
+ {
+ IPACMERR("Filter Config XML read failed, use default configuration \n");
+ }
+
/* Construct the routing table ictol name in iface static member*/
rt_tbl_default_v4.ip = IPA_IP_v4;
strlcpy(rt_tbl_default_v4.name, V4_DEFAULT_ROUTE_TABLE_NAME, sizeof(rt_tbl_default_v4.name));
diff --git a/ipacm/src/IPACM_Filter_cfg.xml b/ipacm/src/IPACM_Filter_cfg.xml
new file mode 100644
index 0000000..39bbd14
--- /dev/null
+++ b/ipacm/src/IPACM_Filter_cfg.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (c) 2021 The Linux Foundation. All rights reserved. -->
+<system xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ipacm_filter_cfg.xsd">
+ <IPACMFilterCfg>
+ <FilteringEnabled>0</FilteringEnabled>
+ <FilterDLAck>0</FilterDLAck>
+ <FilterEntry>
+ <IPFamily>4</IPFamily>
+ <IPV4NextHeaderProtocol>17</IPV4NextHeaderProtocol>
+ </FilterEntry>
+ <FilterEntry>
+ <IPFamily>4</IPFamily>
+ <IPV4NextHeaderProtocol>6</IPV4NextHeaderProtocol>
+ </FilterEntry>
+ </IPACMFilterCfg>
+</system>
diff --git a/ipacm/src/IPACM_IfaceManager.cpp b/ipacm/src/IPACM_IfaceManager.cpp
index 1392a1a..a2e9b66 100644
--- a/ipacm/src/IPACM_IfaceManager.cpp
+++ b/ipacm/src/IPACM_IfaceManager.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2021, 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
@@ -286,6 +286,7 @@
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, lan);
#endif
IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, lan); // register for IPA_CFG_CHANGE event
+ IPACM_EvtDispatcher::registr(IPA_FILTER_CFG_CHANGE_EVENT, lan); // register for IPA_FILTER_CFG_CHANGE_EVENT event
IPACM_EvtDispatcher::registr(IPA_PRIVATE_SUBNET_CHANGE_EVENT, lan); // register for IPA_PRIVATE_SUBNET_CHANGE_EVENT event
#ifdef FEATURE_IPA_ANDROID
IPACM_EvtDispatcher::registr(IPA_TETHERING_STATS_UPDATE_EVENT, lan);
@@ -483,6 +484,7 @@
IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, w);
IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, w);
IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, w); // register for IPA_CFG_CHANGE event
+ IPACM_EvtDispatcher::registr(IPA_FILTER_CFG_CHANGE_EVENT, w); // register for IPA_FILTER_CFG_CHANGE_EVENT event
IPACM_EvtDispatcher::registr(IPA_WAN_XLAT_CONNECT_EVENT, w);
if(is_sta_mode == WLAN_WAN)
{
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
index bffcd8e..e2beea6 100644
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -57,6 +57,8 @@
#endif
bool IPACM_Lan::odu_up = false;
+struct ipa_lan_downstream_info IPACM_Lan::downstream_info[IPA_MAX_TETHER_IFACE_ENTRIES];
+
IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index)
{
num_eth_client = 0;
@@ -133,6 +135,7 @@
memset(ipv6_prefix_flt_rule_hdl, 0, (NUM_IPV6_PREFIX_FLT_RULE + NUM_IPV6_PREFIX_MTU_RULE) * sizeof(uint32_t));
memset(ipv6_icmp_flt_rule_hdl, 0, NUM_IPV6_ICMP_FLT_RULE * sizeof(uint32_t));
memset(ipv6_prefix, 0, sizeof(ipv6_prefix));
+ memset(filter_cfg_rule_hdl, 0, sizeof(filter_cfg_rule_hdl));
/* ODU routing table initilization */
if(ipa_if_cate == ODU_IF)
@@ -275,6 +278,20 @@
}
break;
+ case IPA_FILTER_CFG_CHANGE_EVENT:
+ {
+ IPACMDBG_H("Received IPA_FILTER_CFG_CHANGE_EVENT");
+
+ /* IPA_IP_MAX means both ipv4 and ipv6 */
+ if ((ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
+ && IPACM_Wan::isWanUP(ipa_if_num))
+ {
+ handle_filter_cfg_update(IPA_IP_v4);
+ }
+
+ }
+ break;
+
case IPA_PRIVATE_SUBNET_CHANGE_EVENT:
{
ipacm_event_data_fid *data = (ipacm_event_data_fid *)param;
@@ -398,6 +415,8 @@
#ifdef FEATURE_IPA_ANDROID
add_dummy_private_subnet_flt_rule(data->iptype);
handle_private_subnet_android(data->iptype);
+ add_dummy_filter_cfg_rules(data->iptype);
+ handle_filter_cfg_update(data->iptype);
#else
handle_private_subnet(data->iptype);
#endif // FEATURE_IPA_ANDROID end
@@ -418,6 +437,8 @@
#ifdef FEATURE_IPA_ANDROID
add_dummy_private_subnet_flt_rule(data->iptype);
handle_private_subnet_android(data->iptype);
+ add_dummy_filter_cfg_rules(data->iptype);
+ handle_filter_cfg_update(data->iptype);
#else
handle_private_subnet(data->iptype);
#endif // FEATURE_IPA_ANDROID end
@@ -755,7 +776,9 @@
if (data->prefix.iptype < IPA_IP_MAX && is_downstream_set[data->prefix.iptype] == false)
{
IPACMDBG_H("Add downstream for IP iptype %d\n", data->prefix.iptype);
+
is_downstream_set[data->prefix.iptype] = true;
+ store_downstream_state(true, data->prefix.iptype);
memcpy(&prefix[data->prefix.iptype], &data->prefix,
sizeof(prefix[data->prefix.iptype]));
@@ -808,7 +831,7 @@
{
IPACMDBG_H("Del downstream for IP iptype %d.\n", data->prefix.iptype);
is_downstream_set[data->prefix.iptype] = false;
-
+ store_downstream_state(false, data->prefix.iptype);
if (is_upstream_set[data->prefix.iptype] == true)
{
IPACMDBG_H("Upstream was set before, deleting UL rules.\n");
@@ -1147,6 +1170,71 @@
return;
}
+void IPACM_Lan::store_downstream_state(bool up, enum ipa_ip_type iptype)
+{
+ /* Store the downstream state. */
+ FILE *fp = NULL;
+ bool state_update = false;
+ int free_index = -1;
+
+ /* Return if other iptype is active. */
+ if ((iptype == IPA_IP_v4 && is_downstream_set[IPA_IP_v6]) ||
+ (iptype == IPA_IP_v6 && is_downstream_set[IPA_IP_v4]))
+ return;
+
+ /* Update the downstream state info. */
+ for (int i=0; i < IPA_MAX_TETHER_IFACE_ENTRIES; i++)
+ {
+ if (IPACM_Lan::downstream_info[i].entry_in_use &&
+ strncmp(dev_name, IPACM_Lan::downstream_info[i].dev_name, IF_NAME_LEN) == 0)
+ {
+ /* Update state. */
+ IPACM_Lan::downstream_info[i].downstream_state = up;
+ state_update = true;
+ IPACMDBG_H("Updating info for tether iface :%s, State: %s\n", dev_name,
+ up ? "UP" : "DOWN");
+ break;
+ }
+
+ if (!IPACM_Lan::downstream_info[i].entry_in_use && free_index == -1)
+ free_index = i;
+ }
+
+ /* if state is up, check if entry is already present, if not add. */
+ if (up && !state_update && free_index != -1)
+ {
+ IPACM_Lan::downstream_info[free_index].entry_in_use = true;
+ IPACM_Lan::downstream_info[free_index].downstream_state = up;
+ strlcpy(IPACM_Lan::downstream_info[free_index].dev_name,
+ dev_name, IF_NAME_LEN);
+ IPACMDBG_H("Adding new tether iface :%s, State: UP\n", dev_name);
+ }
+ else if (!state_update && free_index == -1)
+ {
+ IPACMERR("Exceeded max tether ifaces: not storing info for %s\n", dev_name);
+ return;
+ }
+
+ fp = fopen(IPA_DOWNSTREAM_TETHER_STATE_FILE_NAME, "w");
+ if (fp == NULL)
+ {
+ IPACMERR("Failed to write downstream state to %s, error is %d - %s\n",
+ IPA_DOWNSTREAM_TETHER_STATE_FILE_NAME,
+ errno, strerror(errno));
+ }
+ else
+ {
+ for (int i=0; i < IPA_MAX_TETHER_IFACE_ENTRIES; i++)
+ {
+ if (IPACM_Lan::downstream_info[i].entry_in_use)
+ {
+ fprintf(fp, "DOWNSTREAM=%s,STATE=%s;", IPACM_Lan::downstream_info[i].dev_name,
+ IPACM_Lan::downstream_info[i].downstream_state ? "UP" : "DOWN");
+ }
+ }
+ fclose(fp);
+ }
+}
int IPACM_Lan::handle_del_ipv6_addr(ipacm_event_data_all *data)
{
@@ -1938,6 +2026,9 @@
#endif
/* add MTU rules for ipv4 */
handle_private_subnet_android(IPA_IP_v4);
+ /* Add filter config rules for ipv4 */
+ handle_filter_cfg_update(IPA_IP_v4);
+
/* Update ipv6 MTU here if WAN_v6 is up and filter rules were installed */
if (IPACM_Wan::isWanUP_V6(ipa_if_num))
@@ -3085,6 +3176,18 @@
#endif
}
+ if (is_downstream_set[IPA_IP_v4])
+ {
+ is_downstream_set[IPA_IP_v4] = false;
+ store_downstream_state(false, IPA_IP_v4);
+ }
+
+ if (is_downstream_set[IPA_IP_v6])
+ {
+ is_downstream_set[IPA_IP_v6] = false;
+ store_downstream_state(false, IPA_IP_v6);
+ }
+
/* delete default filter rules */
if (ip_type != IPA_IP_v6 && rx_prop != NULL)
{
@@ -3134,6 +3237,14 @@
IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPACM_Iface::ipacmcfg->ipa_num_private_subnet);
#endif
IPACMDBG_H("Deleted private subnet v4 filter rules successfully.\n");
+
+ if(m_filtering.DeleteFilteringHdls(filter_cfg_rule_hdl, IPA_IP_v4, IPA_MAX_FILTER_CFG_ENTRIES) == false)
+ {
+ IPACMERR("Error deleting filter cfg rules.\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_FILTER_CFG_ENTRIES);
}
IPACMDBG_H("Finished delete default iface ipv4 filtering rules \n ");
@@ -4213,6 +4324,194 @@
return res;
}
+int IPACM_Lan::add_dummy_filter_cfg_rules(ipa_ip_type iptype)
+{
+ int i, len, res = IPACM_SUCCESS;
+ struct ipa_flt_rule_add flt_rule;
+ ipa_ioc_add_flt_rule* pFilteringTable;
+ bool result;
+
+ if(rx_prop == NULL)
+ {
+ IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy filter cfg rules.\n", dev_name);
+ return 0;
+ }
+
+ if(iptype == IPA_IP_v6)
+ {
+ IPACMDBG_H("There is no ipv6 dummy filter config rules needed for iface %s\n", dev_name);
+ return 0;
+ }
+
+ len = sizeof(struct ipa_ioc_add_flt_rule) + IPA_MAX_FILTER_CFG_ENTRIES * sizeof(struct ipa_flt_rule_add);
+
+ pFilteringTable = (struct ipa_ioc_add_flt_rule *)malloc(len);
+ if (pFilteringTable == NULL)
+ {
+ IPACMERR("Error allocate flt table memory...\n");
+ return IPACM_FAILURE;
+ }
+ memset(pFilteringTable, 0, len);
+
+ pFilteringTable->commit = 1;
+ pFilteringTable->ep = rx_prop->rx[0].src_pipe;
+ pFilteringTable->global = false;
+ pFilteringTable->ip = iptype;
+ pFilteringTable->num_rules = IPA_MAX_FILTER_CFG_ENTRIES;
+
+ memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_add));
+
+ flt_rule.rule.retain_hdr = 0;
+ flt_rule.at_rear = true;
+ flt_rule.flt_rule_hdl = -1;
+ flt_rule.status = -1;
+ flt_rule.rule.action = IPA_PASS_TO_EXCEPTION;
+ if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+ flt_rule.rule.hashable = true;
+ memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib,
+ sizeof(flt_rule.rule.attrib));
+
+ if(iptype == IPA_IP_v4)
+ {
+ flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR;
+ flt_rule.rule.attrib.u.v4.src_addr_mask = ~0;
+ flt_rule.rule.attrib.u.v4.src_addr = ~0;
+ flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0;
+ flt_rule.rule.attrib.u.v4.dst_addr = ~0;
+
+ for(i=0; i<IPA_MAX_FILTER_CFG_ENTRIES; i++)
+ {
+ memcpy(&(pFilteringTable->rules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add));
+ }
+
+#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
+ /* use index hw-counter */
+ if(ipa_if_cate == WLAN_IF && IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
+ {
+ IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL);
+ result = m_filtering.AddFilteringRule_hw_index(pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL);
+ } else {
+ result = m_filtering.AddFilteringRule(pFilteringTable);
+ }
+#else
+ result = m_filtering.AddFilteringRule(pFilteringTable);
+#endif
+
+ if (result == false)
+ {
+ IPACMERR("Error adding dummy filter cfg rules\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ else
+ {
+ IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_FILTER_CFG_ENTRIES);
+ /* copy filter rule hdls */
+ for (int i = 0; i < IPA_MAX_FILTER_CFG_ENTRIES; i++)
+ {
+ if (pFilteringTable->rules[i].status == 0)
+ {
+ filter_cfg_rule_hdl[i] = pFilteringTable->rules[i].flt_rule_hdl;
+ IPACMDBG_H("Filter cfg rule %d hdl:0x%x\n", i, private_fl_rule_hdl[i]);
+ }
+ else
+ {
+ IPACMERR("Failed adding filter cfg rule %d\n", i);
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ }
+ }
+ }
+fail:
+ free(pFilteringTable);
+ return res;
+}
+
+
+int IPACM_Lan::handle_filter_cfg_update(ipa_ip_type iptype)
+{
+ int i, len, res = IPACM_SUCCESS;
+ struct ipa_flt_rule_mdfy flt_rule;
+ struct ipa_ioc_mdfy_flt_rule* pFilteringTable = NULL;
+
+ if (rx_prop == NULL)
+ {
+ IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
+ return IPACM_SUCCESS;
+ }
+
+ if(iptype == IPA_IP_v6)
+ {
+ IPACMDBG_H("Ipv6 Filter config is not supported for iface %s\n", dev_name);
+ return 0;
+ }
+
+ for(i=0; i<IPA_MAX_FILTER_CFG_ENTRIES; i++)
+ {
+ reset_to_dummy_flt_rule(IPA_IP_v4, filter_cfg_rule_hdl[i]);
+ }
+
+ if(IPACM_Iface::ipacmcfg->filter_config.filter_enable == true)
+ {
+ if ((IPACM_Iface::ipacmcfg->filter_config.num_filter_cfg_entries == 0) ||
+ (IPACM_Iface::ipacmcfg->filter_config.num_filter_cfg_entries > IPA_MAX_FILTER_CFG_ENTRIES))
+ {
+ IPACMERR("Invalid filter Config num rules %d\n",
+ IPACM_Iface::ipacmcfg->filter_config.num_filter_cfg_entries);
+ return IPACM_FAILURE;
+ }
+
+ IPACMDBG_H("total %d filter cfg rules are needed\n", IPACM_Iface::ipacmcfg->filter_config.num_filter_cfg_entries);
+
+ len = sizeof(struct ipa_ioc_mdfy_flt_rule) + IPACM_Iface::ipacmcfg->filter_config.num_filter_cfg_entries * sizeof(struct ipa_flt_rule_mdfy);
+ pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len);
+ if (!pFilteringTable)
+ {
+ IPACMERR("Failed to allocate ipa_ioc_mdfy_flt_rule memory...\n");
+ return IPACM_FAILURE;
+ }
+ memset(pFilteringTable, 0, len);
+
+ pFilteringTable->commit = 1;
+ pFilteringTable->ip = iptype;
+ pFilteringTable->num_rules = (uint8_t)IPACM_Iface::ipacmcfg->filter_config.num_filter_cfg_entries;
+
+ for (i = 0; i < IPACM_Iface::ipacmcfg->filter_config.num_filter_cfg_entries; i++)
+ {
+ /* add filter cfg for ipv4 */
+ memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy));
+ flt_rule.status = -1;
+ flt_rule.rule.retain_hdr = 1;
+ flt_rule.rule.to_uc = 0;
+ flt_rule.rule.action = IPA_PASS_TO_EXCEPTION;
+ flt_rule.rule.eq_attrib_type = 0;
+ if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+ flt_rule.rule.hashable = true;
+ flt_rule.rule_hdl = filter_cfg_rule_hdl[i];
+ memcpy(&flt_rule.rule.attrib,
+ &IPACM_Iface::ipacmcfg->filter_config.filter_cfg_entries[i].attrib,
+ sizeof(struct ipa_rule_attrib));
+ flt_rule.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask;
+ memcpy(&(pFilteringTable->rules[i]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy));
+ }
+
+ if (false == m_filtering.ModifyFilteringRule(pFilteringTable))
+ {
+ IPACMERR("Failed to modify filter config rules.\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ }
+fail:
+ if(pFilteringTable != NULL)
+ {
+ free(pFilteringTable);
+ }
+ return res;
+}
+
+
int IPACM_Lan::handle_private_subnet_android(ipa_ip_type iptype)
{
int i, len, res = IPACM_SUCCESS;
diff --git a/ipacm/src/IPACM_Main.cpp b/ipacm/src/IPACM_Main.cpp
index 6bd117e..e29289d 100644
--- a/ipacm/src/IPACM_Main.cpp
+++ b/ipacm/src/IPACM_Main.cpp
@@ -80,9 +80,10 @@
#define IPACM_FIREWALL_FILE_NAME "mobileap_firewall.xml"
#define IPACM_CFG_FILE_NAME "IPACM_cfg.xml"
+#define IPACM_FILTER_CFG_FILE_NAME "IPACM_Filter_cfg.xml"
#ifdef FEATURE_IPA_ANDROID
#define IPACM_PID_FILE "/data/vendor/ipa/ipacm.pid"
-#define IPACM_DIR_NAME "/data"
+#define IPACM_DIR_NAME "/data/vendor/ipa/"
#else/* defined(FEATURE_IPA_ANDROID) */
#define IPACM_PID_FILE "/etc/ipacm.pid"
#define IPACM_DIR_NAME "/etc"
@@ -146,8 +147,8 @@
return NULL;
}
-/* start firewall-rule monitor*/
-void* firewall_monitor(void *param)
+/* start Config change monitor*/
+void* cfg_change_monitor(void *param)
{
int length;
int wd;
@@ -196,6 +197,7 @@
{
IPACMDBG_H("The directory %s was 0x%x\n", event->name, event->mask);
}
+#ifndef FEATURE_IPA_ANDROID
else if (!strncmp(event->name, IPACM_FIREWALL_FILE_NAME, event->len)) // firewall_rule change
{
IPACMDBG_H("File \"%s\" was 0x%x\n", event->name, event->mask);
@@ -218,6 +220,33 @@
/* Insert IPA_FIREWALL_CHANGE_EVENT to command queue */
IPACM_EvtDispatcher::PostEvt(&evt_data);
}
+#endif
+ else if (!strncmp(event->name, IPACM_FILTER_CFG_FILE_NAME, event->len)) // IPACM Filter Config change
+ {
+ char IPACM_config_file[IPA_MAX_FILE_LEN];
+ IPACMDBG_H("File \"%s\" was 0x%x\n", event->name, event->mask);
+ IPACMDBG_H("The interested file %s .\n", IPACM_FILTER_CFG_FILE_NAME);
+
+ /* default fillter config is disable. */
+ memset(&IPACM_Iface::ipacmcfg->filter_config, 0,
+ sizeof(IPACM_Iface::ipacmcfg->filter_config));
+ strlcpy(IPACM_config_file, IPACM_FILTER_CFG_FILE, sizeof(IPACM_config_file));
+ if (IPACM_SUCCESS == IPACM_read_filter_cfg_xml(IPACM_config_file,
+ &IPACM_Iface::ipacmcfg->filter_config))
+ {
+ IPACMDBG_H("Filter XML read OK \n");
+ }
+ else
+ {
+ IPACMERR("Filter Config XML read failed, use default configuration \n");
+ }
+
+ evt_data.event = IPA_FILTER_CFG_CHANGE_EVENT;
+ evt_data.evt_data = NULL;
+
+ /* Insert IPA_FILTER_CFG_CHANGE_EVENT to command queue */
+ IPACM_EvtDispatcher::PostEvt(&evt_data);
+ }
}
IPACMDBG_H("Received monitoring event %s.\n", event->name);
}
@@ -1035,23 +1064,20 @@
}
}
- /* Enable Firewall support only on MDM targets */
-#ifndef FEATURE_IPA_ANDROID
if (IPACM_SUCCESS == monitor_thread)
{
- ret = pthread_create(&monitor_thread, NULL, firewall_monitor, NULL);
+ ret = pthread_create(&monitor_thread, NULL, cfg_change_monitor, NULL);
if (IPACM_SUCCESS != ret)
{
IPACMERR("unable to create monitor thread\n");
return ret;
}
- IPACMDBG_H("created firewall monitor thread\n");
- if(pthread_setname_np(monitor_thread, "firewall cfg process") != 0)
+ IPACMDBG_H("created config change monitor thread\n");
+ if(pthread_setname_np(monitor_thread, "config change monitor") != 0)
{
IPACMERR("unable to set thread name\n");
}
}
-#endif
if (IPACM_SUCCESS == ipa_driver_thread)
{
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
index 2ee9f2c..c555481 100644
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2021 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
@@ -1155,6 +1155,31 @@
}
break;
+ case IPA_FILTER_CFG_CHANGE_EVENT:
+ {
+ IPACMDBG_H("Received IPA_FILTER_CFG_CHANGE_EVENT\n");
+
+ if(m_is_sta_mode == Q6_WAN)
+ {
+ if(is_default_gateway == false)
+ {
+ IPACMDBG_H("Interface %s is not default gw, return.\n", dev_name);
+ return;
+ }
+
+ if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
+ {
+ del_wan_firewall_rule(IPA_IP_v4);
+ config_wan_firewall_rule(IPA_IP_v4);
+ install_wan_filtering_rule(false);
+ }
+ else
+ {
+ IPACMERR("IP type is not expected.\n");
+ }
+ }
+ }
+ break;
case IPA_COALESCE_NOTICE:
{
if (m_is_sta_mode == Q6_WAN)
@@ -2395,6 +2420,20 @@
IPACMERR("Failed to send WAN_IOC_NOTIFY_WAN_STATE as up %d\n ", wan_state.up);
}
close(fd_wwan_ioctl);
+
+ /* Store the Offload state. */
+ FILE *fp = NULL;
+ fp = fopen(IPA_OFFLOAD_TETHER_STATE_FILE_NAME, "w");
+ if (fp == NULL)
+ {
+ IPACMERR("Failed to write offload state to %s, error is %d - %s\n",
+ IPA_OFFLOAD_TETHER_STATE_FILE_NAME, errno, strerror(errno));
+ }
+ else
+ {
+ fprintf(fp, "UPSTREAM=%s,STATE=UP", dev_name);
+ fclose(fp);
+ }
}
ipa_pm_q6_check++;
IPACMDBG_H("update ipa_pm_q6_check to %d\n", ipa_pm_q6_check);
@@ -4079,6 +4118,82 @@
return IPACM_SUCCESS;
}
+/* configure the DL Ack rule if enabled */
+int IPACM_Wan::config_filter_dl_ack_rule_ex(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype)
+{
+ struct ipa_flt_rule_add flt_rule_entry;
+ ipa_ioc_get_rt_tbl_indx rt_tbl_idx;
+ ipa_ioc_generate_flt_eq flt_eq;
+
+ IPACMDBG_H("ip-family: %d; \n", iptype);
+
+ if (rx_prop == NULL)
+ {
+ IPACMDBG_H("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;
+ }
+
+ if (iptype == IPA_IP_v4)
+ {
+ 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;
+ if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+ flt_rule_entry.rule.hashable = false;
+ memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
+ rt_tbl_idx.ip = iptype;
+ strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
+ rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
+ 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_H("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(flt_rule_entry.rule.attrib));
+ flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_IS_PURE_ACK;
+
+ 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[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
+ IPACMDBG_H("Filter rule attrib mask: 0x%x\n", rules[rule_offset].rule.attrib.attrib_mask);
+ IPACM_Wan::num_v4_flt_rule++;
+ IPACMDBG_H("Constructed DL Ack rule for ip type %d\n", iptype);
+ }
+ return IPACM_SUCCESS;
+}
+
+
int IPACM_Wan::init_fl_rule_ex(ipa_ip_type iptype)
{
int res = IPACM_SUCCESS;
@@ -4403,6 +4518,19 @@
}
IPACMDBG_H("Succeded in constructing ICMP/ALG rules for ip type %d\n", iptype);
+ /* Install DL ACK Rule if enabled. */
+ if (IPACM_Iface::ipacmcfg->filter_config.filter_enable &&
+ IPACM_Iface::ipacmcfg->filter_config.dl_ack_filter_enable)
+ {
+ if(IPACM_FAILURE == config_filter_dl_ack_rule_ex(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4))
+ {
+ IPACMERR("Failed to add DL ack filter rules.\n");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ IPACMDBG_H("Succeded in constructing DL ACK rule 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");
@@ -5073,6 +5201,20 @@
IPACMERR("Failed to send WAN_IOC_NOTIFY_WAN_STATE as up %d\n ", wan_state.up);
}
close(fd_wwan_ioctl);
+
+ /* Store the Offload state. */
+ FILE *fp = NULL;
+ fp = fopen(IPA_OFFLOAD_TETHER_STATE_FILE_NAME, "w");
+ if (fp == NULL)
+ {
+ IPACMERR("Failed to write offload state to %s, error is %d - %s\n",
+ IPA_OFFLOAD_TETHER_STATE_FILE_NAME, errno, strerror(errno));
+ }
+ else
+ {
+ fprintf(fp, "UPSTREAM=%s,STATE=DOWN", dev_name);
+ fclose(fp);
+ }
}
if (ipa_pm_q6_check > 0)
ipa_pm_q6_check--;
diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp
index eeb4b01..58bbeee 100644
--- a/ipacm/src/IPACM_Wlan.cpp
+++ b/ipacm/src/IPACM_Wlan.cpp
@@ -566,6 +566,7 @@
{
IPACMDBG_H("Add downstream for IP iptype %d.\n", data->prefix.iptype);
is_downstream_set[data->prefix.iptype] = true;
+ store_downstream_state(true, data->prefix.iptype);
memcpy(&prefix[data->prefix.iptype], &data->prefix,
sizeof(prefix[data->prefix.iptype]));
@@ -616,7 +617,7 @@
{
IPACMDBG_H("Del downstream for IP iptype %d.\n", data->prefix.iptype);
is_downstream_set[data->prefix.iptype] = false;
-
+ store_downstream_state(false, data->prefix.iptype);
if(is_upstream_set[data->prefix.iptype] == true)
{
IPACMDBG_H("Upstream was set before, deleting UL rules.\n");
@@ -1940,6 +1941,18 @@
}
IPACMDBG_H("finished deleting wan filtering rules\n ");
+ if (is_downstream_set[IPA_IP_v4])
+ {
+ is_downstream_set[IPA_IP_v4] = false;
+ store_downstream_state(false, IPA_IP_v4);
+ }
+
+ if (is_downstream_set[IPA_IP_v6])
+ {
+ is_downstream_set[IPA_IP_v6] = false;
+ store_downstream_state(false, IPA_IP_v6);
+ }
+
/* Delete v4 filtering rules */
if (ip_type != IPA_IP_v6 && rx_prop != NULL)
{
diff --git a/ipacm/src/IPACM_Xml.cpp b/ipacm/src/IPACM_Xml.cpp
index 28b7af5..7886550 100644
--- a/ipacm/src/IPACM_Xml.cpp
+++ b/ipacm/src/IPACM_Xml.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013, 2019-2020, The Linux Foundation. All rights reserved.
+Copyright (c) 2013, 2019-2021, 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
@@ -68,6 +68,12 @@
IPACM_firewall_conf_t *config
);
+static int IPACM_filter_cfg_xml_parse_tree
+(
+ xmlNode* xml_node,
+ IPACM_filter_conf_t *config
+);
+
/*Reads content (stored as child) of the element */
static char* IPACM_read_content_element
(
@@ -610,7 +616,7 @@
memset(content_buf, 0, sizeof(content_buf));
memcpy(content_buf, (void *)content, str_size);
config->extd_firewall_entries[config->num_extd_firewall_entries - 1].ip_vsn
- = (firewall_ip_version_enum)atoi(content_buf);
+ = (ip_version_enum)atoi(content_buf);
IPACMDBG_H("\n IP family type is %d \n",
config->extd_firewall_entries[config->num_extd_firewall_entries - 1].ip_vsn);
}
@@ -1220,3 +1226,739 @@
} /* end while */
return ret_val;
}
+
+/* This function read Filter Cfg XML and populate the Filter Cfg */
+int IPACM_read_filter_cfg_xml(char *xml_file, IPACM_filter_conf_t *config)
+{
+ xmlDocPtr doc = NULL;
+ xmlNode* root = NULL;
+ int ret_val;
+
+ IPACM_ASSERT(xml_file != NULL);
+ IPACM_ASSERT(config != NULL);
+
+ /* invoke the XML parser and obtain the parse tree */
+ doc = xmlReadFile(xml_file, "UTF-8", XML_PARSE_NOBLANKS);
+ if (doc == NULL) {
+ IPACMDBG_H("IPACM_xml_parse: libxml returned parse error\n");
+ return IPACM_FAILURE;
+ }
+ /*get the root of the tree*/
+ root = xmlDocGetRootElement(doc);
+
+ /* parse the xml tree returned by libxml*/
+ ret_val = IPACM_filter_cfg_xml_parse_tree(root, config);
+
+ if (ret_val != IPACM_SUCCESS)
+ {
+ IPACMDBG_H("IPACM_xml_parse: IPACM_filter_cfg_xml_parse_tree returned parse error!\n");
+ }
+
+ /* free the tree */
+ xmlFreeDoc(doc);
+
+ return ret_val;
+}
+
+/* This function traverses the filter cfg xml tree */
+static int IPACM_filter_cfg_xml_parse_tree
+(
+ xmlNode* xml_node,
+ IPACM_filter_conf_t *config
+)
+{
+ int mask_value_v6, mask_index;
+ int32_t ret_val = IPACM_SUCCESS;
+ char *content;
+ int str_size;
+ char content_buf[MAX_XML_STR_LEN];
+ struct in6_addr ip6_addr;
+
+ IPACM_ASSERT(config != NULL);
+
+ if (NULL == xml_node)
+ return ret_val;
+
+ while ( xml_node != NULL )
+ {
+ switch (xml_node->type)
+ {
+
+ case XML_ELEMENT_NODE:
+ {
+ if (0 == IPACM_util_icmp_string((char*)xml_node->name, system_TAG) ||
+ 0 == IPACM_util_icmp_string((char*)xml_node->name, FilterCfg_TAG) ||
+ 0 == IPACM_util_icmp_string((char*)xml_node->name, FilterEntry_TAG) ||
+ 0 == IPACM_util_icmp_string((char*)xml_node->name, FilterEnabled_TAG) ||
+ 0 == IPACM_util_icmp_string((char*)xml_node->name, FilterDLAck_TAG))
+ {
+ if (0 == IPACM_util_icmp_string((char*)xml_node->name, FilterEntry_TAG))
+ {
+ /* increase Filter Config entry num */
+ config->num_filter_cfg_entries++;
+ }
+
+ if (0 == IPACM_util_icmp_string((char*)xml_node->name, FilterEnabled_TAG))
+ {
+ /* setup action of matched rules */
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ if (atoi(content_buf)==1)
+ {
+ config->filter_enable = true;
+ }
+ else
+ {
+ config->filter_enable = false;
+ }
+ IPACMDBG_H(" Filter Config Enabled :%d\n",config->filter_enable);
+ }
+ }
+
+ if (0 == IPACM_util_icmp_string((char*)xml_node->name, FilterDLAck_TAG))
+ {
+ /* setup if DL Ack filtering enabled or not */
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ if (atoi(content_buf)==1)
+ {
+ config->dl_ack_filter_enable = true;
+ }
+ else
+ {
+ config->dl_ack_filter_enable = false;
+ }
+ IPACMDBG_H(" DL Ack Filtering Enabled:%d\n", config->dl_ack_filter_enable);
+ }
+ }
+ /* go to child */
+ ret_val = IPACM_filter_cfg_xml_parse_tree(xml_node->children, config);
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPFamily_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].ip_vsn
+ = (ip_version_enum)atoi(content_buf);
+ IPACMDBG_H("\n IP family type is %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].ip_vsn);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4SourceAddress_TAG))
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_ADDR;
+ /* go to child */
+ ret_val = IPACM_filter_cfg_xml_parse_tree(xml_node->children, config);
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4SourceIPAddress_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ content_buf[MAX_XML_STR_LEN-1] = '\0';
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v4.src_addr
+ = ntohl(inet_addr(content_buf));
+ IPACMDBG_H("IPv4 source address is: %s \n", content_buf);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4SourceSubnetMask_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ content_buf[MAX_XML_STR_LEN-1] = '\0';
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v4.src_addr_mask
+ = ntohl(inet_addr(content_buf));
+ IPACMDBG_H("IPv4 source subnet mask is: %s \n", content_buf);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4DestinationAddress_TAG))
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_ADDR;
+ /* go to child */
+ ret_val = IPACM_filter_cfg_xml_parse_tree(xml_node->children, config);
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4DestinationIPAddress_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ content_buf[MAX_XML_STR_LEN-1] = '\0';
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v4.dst_addr
+ = ntohl(inet_addr(content_buf));
+ IPACMDBG_H("IPv4 destination address is: %s \n", content_buf);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4DestinationSubnetMask_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ content_buf[MAX_XML_STR_LEN-1] = '\0';
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v4.dst_addr_mask
+ = ntohl(inet_addr(content_buf));
+ IPACMDBG_H("IPv4 destination subnet mask is: %s \n", content_buf);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4TypeOfService_TAG))
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_TOS;
+ /* go to child */
+ ret_val = IPACM_filter_cfg_xml_parse_tree(xml_node->children, config);
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TOSValue_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v4.tos
+ = atoi(content_buf);
+ // Here we do not know if it is TOS with mask or not, so we put at both places
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.tos_value
+ = atoi(content_buf);
+ IPACMDBG_H("\n IPV4 TOS val is %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v4.tos);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TOSMask_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ uint8_t mask;
+
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ mask = atoi(content_buf);
+ IPACMDBG_H("\n IPv4 TOS mask is %u \n", mask);
+ if (mask != 0xFF) {
+ // TOS attribute cannot be used
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v4.tos = 0;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.tos_mask = mask;
+
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |=
+ IPA_FLT_TOS_MASKED;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask &=
+ ~IPA_FLT_TOS;
+ } else {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.tos_value = 0;
+ }
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4NextHeaderProtocol_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_PROTOCOL;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v4.protocol = atoi(content_buf);
+ IPACMDBG_H("\n IPv4 next header prot is %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v4.protocol);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6SourceAddress_TAG))
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |=
+ IPA_FLT_SRC_ADDR;
+ /* go to child */
+ ret_val = IPACM_filter_cfg_xml_parse_tree(xml_node->children, config);
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6SourceIPAddress_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ inet_pton(AF_INET6, content_buf, &ip6_addr);
+ memcpy(config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.src_addr,
+ ip6_addr.s6_addr, IPACM_IPV6_ADDR_LEN * sizeof(uint8_t));
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.src_addr[0]=ntohl(config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.src_addr[0]);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.src_addr[1]=ntohl(config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.src_addr[1]);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.src_addr[2]=ntohl(config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.src_addr[2]);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.src_addr[3]=ntohl(config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.src_addr[3]);
+
+ IPACMDBG_H("\n ipv6 source addr is %d \n ",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.src_addr[0]);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6SourcePrefix_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ mask_value_v6 = atoi(content_buf);
+ for (mask_index = 0; mask_index < 4; mask_index++)
+ {
+ if (mask_value_v6 >= 32)
+ {
+ mask_v6(32, &(config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.src_addr_mask[mask_index]));
+ mask_value_v6 -= 32;
+ }
+ else
+ {
+ mask_v6(mask_value_v6, &(config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.src_addr_mask[mask_index]));
+ mask_value_v6 = 0;
+ }
+ }
+ IPACMDBG_H("\n ipv6 source prefix is %d \n", atoi(content_buf));
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6DestinationAddress_TAG))
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |=
+ IPA_FLT_DST_ADDR;
+ /* go to child */
+ ret_val = IPACM_filter_cfg_xml_parse_tree(xml_node->children, config);
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6DestinationIPAddress_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ inet_pton(AF_INET6, content_buf, &ip6_addr);
+ memcpy(config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.dst_addr,
+ ip6_addr.s6_addr, IPACM_IPV6_ADDR_LEN * sizeof(uint8_t));
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.dst_addr[0]=ntohl(config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.dst_addr[0]);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.dst_addr[1]=ntohl(config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.dst_addr[1]);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.dst_addr[2]=ntohl(config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.dst_addr[2]);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.dst_addr[3]=ntohl(config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.dst_addr[3]);
+ IPACMDBG_H("\n ipv6 dest addr is %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.dst_addr[0]);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6DestinationPrefix_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ mask_value_v6 = atoi(content_buf);
+ for (mask_index = 0; mask_index < 4; mask_index++)
+ {
+ if (mask_value_v6 >= 32)
+ {
+ mask_v6(32, &(config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.dst_addr_mask[mask_index]));
+ mask_value_v6 -= 32;
+ }
+ else
+ {
+ mask_v6(mask_value_v6, &(config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.dst_addr_mask[mask_index]));
+ mask_value_v6 = 0;
+ }
+ }
+ IPACMDBG_H("\n ipv6 dest prefix is %d \n", atoi(content_buf));
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6TrafficClass_TAG))
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_TC;
+ /* go to child */
+ ret_val = IPACM_filter_cfg_xml_parse_tree(xml_node->children, config);
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TrfClsValue_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.tc
+ = atoi(content_buf);
+ IPACMDBG_H("\n ipv6 trf class val is %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.tc);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TrfClsMask_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.tc
+ &= atoi(content_buf);
+ IPACMDBG_H("\n ipv6 trf class mask is %d \n", atoi(content_buf));
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6NextHeaderProtocol_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.next_hdr
+ = atoi(content_buf);
+ IPACMDBG_H("\n ipv6 next header protocol is %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.u.v6.next_hdr);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPSource_TAG))
+ {
+ /* go to child */
+ ret_val = IPACM_filter_cfg_xml_parse_tree(xml_node->children, config);
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPSourcePort_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port
+ = atoi(content_buf);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPSourceRange_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ if (atoi(content_buf) != 0)
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT_RANGE;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port_lo
+ = config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port_hi
+ = config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port + atoi(content_buf);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port = 0;
+ IPACMDBG_H("\n tcp source port from %d to %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port_lo,
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port_hi);
+ }
+ else
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT;
+ IPACMDBG_H("\n tcp source port= %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port);
+ }
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPDestination_TAG))
+ {
+ /* go to child */
+ ret_val = IPACM_filter_cfg_xml_parse_tree(xml_node->children, config);
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPDestinationPort_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port
+ = atoi(content_buf);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPDestinationRange_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ if(atoi(content_buf)!=0)
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT_RANGE;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port_lo
+ = config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port_hi
+ = config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port + atoi(content_buf);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port = 0;
+ IPACMDBG_H("\n tcp dest port from %d to %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port_lo,
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port_hi);
+ }
+ else
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT;
+ IPACMDBG_H("\n tcp dest port= %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port);
+ }
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPSource_TAG))
+ {
+ /* go to child */
+ ret_val = IPACM_filter_cfg_xml_parse_tree(xml_node->children, config);
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPSourcePort_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port
+ = atoi(content_buf);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPSourceRange_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ if(atoi(content_buf)!=0)
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT_RANGE;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port_lo
+ = config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port_hi
+ = config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port + atoi(content_buf);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port = 0;
+ IPACMDBG_H("\n udp source port from %d to %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port_lo,
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port_hi);
+ }
+ else
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT;
+ IPACMDBG_H("\n udp source port= %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port);
+ }
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPDestination_TAG))
+ {
+ /* go to child */
+ ret_val = IPACM_filter_cfg_xml_parse_tree(xml_node->children, config);
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPDestinationPort_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port
+ = atoi(content_buf);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPDestinationRange_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ if(atoi(content_buf)!=0)
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT_RANGE;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port_lo
+ = config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port_hi
+ = config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port + atoi(content_buf);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port = 0;
+ IPACMDBG_H("\n UDP dest port from %d to %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port_lo,
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port_hi);
+ }
+ else
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT;
+ IPACMDBG_H("\n UDP dest port= %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port);
+ }
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, ICMPType_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.type = atoi(content_buf);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_TYPE;
+ IPACMDBG_H("\n icmp type is %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.type);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, ICMPCode_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.code = atoi(content_buf);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_CODE;
+ IPACMDBG_H("\n icmp code is %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.code);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, ESPSPI_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.spi = atoi(content_buf);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_SPI;
+ IPACMDBG_H("\n esp spi is %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.spi);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPSource_TAG))
+ {
+ /* go to child */
+ ret_val = IPACM_filter_cfg_xml_parse_tree(xml_node->children, config);
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPSourcePort_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content,str_size);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port
+ = atoi(content_buf);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPSourceRange_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ if(atoi(content_buf)!=0)
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT_RANGE;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port_lo
+ = config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port_hi
+ = config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port + atoi(content_buf);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port = 0;
+ IPACMDBG_H("\n tcp_udp source port from %d to %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port_lo,
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port_hi);
+ }
+ else
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT;
+ IPACMDBG_H("\n tcp_udp source port= %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.src_port);
+
+ }
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPDestination_TAG))
+ {
+ ret_val = IPACM_filter_cfg_xml_parse_tree(xml_node->children, config);
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPDestinationPort_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port
+ = atoi(content_buf);
+ }
+ }
+ else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPDestinationRange_TAG))
+ {
+ content = IPACM_read_content_element(xml_node);
+ if (content)
+ {
+ str_size = strlen(content);
+ memset(content_buf, 0, sizeof(content_buf));
+ memcpy(content_buf, (void *)content, str_size);
+ if(atoi(content_buf)!=0)
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT_RANGE;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port_lo
+ = config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port;
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port_hi
+ = config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port + atoi(content_buf);
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port = 0;
+ IPACMDBG_H("\n tcp_udp dest port from %d to %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port_lo,
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port_hi);
+ }
+ else
+ {
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT;
+ IPACMDBG_H("\n tcp_udp dest port= %d \n",
+ config->filter_cfg_entries[config->num_filter_cfg_entries - 1].attrib.dst_port);
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ /* go to sibling */
+ xml_node = xml_node->next;
+ } /* end while */
+ return ret_val;
+}
+
diff --git a/ipacm/src/ipacm.rc b/ipacm/src/ipacm.rc
index c1c876b..ec20898 100644
--- a/ipacm/src/ipacm.rc
+++ b/ipacm/src/ipacm.rc
@@ -1,4 +1,4 @@
-# Copyright (c) 2019, The Linux Foundation. All rights reserved.
+# Copyright (c) 2019-2021, 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
@@ -32,3 +32,8 @@
on post-fs
start vendor.ipacm
+
+on post-fs-data
+ #create prebuilt filter cfg xml file
+ copy /vendor/etc/IPACM_Filter_cfg.xml /data/vendor/ipa/IPACM_Filter_cfg.xml
+ chown radio radio /data/vendor/ipa/IPACM_Filter_cfg.xml
diff --git a/ipacm_vendor_product.mk b/ipacm_vendor_product.mk
index 57b7dc3..699f19e 100644
--- a/ipacm_vendor_product.mk
+++ b/ipacm_vendor_product.mk
@@ -2,6 +2,7 @@
#IPACM_DATA
IPACM_DATA += IPACM_cfg.xml
+IPACM_DATA += IPACM_Filter_cfg.xml
IPACM_DATA += ipacm
IPACM_DATA += ipacm.rc