IPACM: Fix AP+STA mode FTP loca-subnet disconnect issue
In AP+STA mode, usb-client can download FTP if FTP server
outside the subnet of external AP. However if the FTP server
is insided the same subnet as external-AP, the FTP download
will failed, also TCP UL/DL is not working properly. The fix
is to construct headers/routing rules for each wifi-client
which is connected to the same external AP's subnet.
Change-Id: I839d33d34b4fd544381b9cf7bd2ba20b51a17551
diff --git a/ipacm/inc/IPACM_ConntrackListener.h b/ipacm/inc/IPACM_ConntrackListener.h
index c1249c2..db83598 100644
--- a/ipacm/inc/IPACM_ConntrackListener.h
+++ b/ipacm/inc/IPACM_ConntrackListener.h
@@ -47,6 +47,7 @@
#endif
#define MAX_NAT_IFACES 50
+#define MAX_STA_CLNT_IFACES 10
using namespace std;
@@ -54,46 +55,49 @@
{
private:
- bool isCTReg;
- bool isNatThreadStart;
- bool WanUp;
- NatApp *nat_inst;
+ bool isCTReg;
+ bool isNatThreadStart;
+ bool WanUp;
+ NatApp *nat_inst;
- int NatIfaceCnt;
- NatIfaces *pNatIfaces;
- uint32_t nat_iface_ipv4_addr[MAX_NAT_IFACES];
- uint32_t nonnat_iface_ipv4_addr[MAX_NAT_IFACES];
- IPACM_Config *pConfig;
+ int NatIfaceCnt;
+ int StaClntCnt;
+ NatIfaces *pNatIfaces;
+ uint32_t nat_iface_ipv4_addr[MAX_NAT_IFACES];
+ uint32_t nonnat_iface_ipv4_addr[MAX_NAT_IFACES];
+ uint32_t sta_clnt_ipv4_addr[MAX_STA_CLNT_IFACES];
+ IPACM_Config *pConfig;
#ifdef CT_OPT
- IPACM_LanToLan *p_lan2lan;
+ IPACM_LanToLan *p_lan2lan;
#endif
- void ProcessCTMessage(void *);
- void ProcessTCPorUDPMsg(struct nf_conntrack *,
- enum nf_conntrack_msg_type, u_int8_t);
- void TriggerWANUp(void *);
- void TriggerWANDown(uint32_t);
- int CreateNatThreads(void);
- int CreateConnTrackThreads(void);
+ void ProcessCTMessage(void *);
+ void ProcessTCPorUDPMsg(struct nf_conntrack *,
+ enum nf_conntrack_msg_type, u_int8_t);
+ void TriggerWANUp(void *);
+ void TriggerWANDown(uint32_t);
+ int CreateNatThreads(void);
+ int CreateConnTrackThreads(void);
#ifdef CT_OPT
- void ProcessCTV6Message(void *);
+ void ProcessCTV6Message(void *);
#endif
public:
- char wan_ifname[IPA_IFACE_NAME_LEN];
- uint32_t wan_ipaddr;
- bool isStaMode;
-
- IPACM_ConntrackListener();
- void event_callback(ipa_cm_event_id, void *data);
- inline bool isWanUp()
- {
+ char wan_ifname[IPA_IFACE_NAME_LEN];
+ uint32_t wan_ipaddr;
+ bool isStaMode;
+ IPACM_ConntrackListener();
+ void event_callback(ipa_cm_event_id, void *data);
+ inline bool isWanUp()
+ {
return WanUp;
- }
+ }
- void HandleNeighIpAddrAddEvt(ipacm_event_data_all *);
- void HandleNeighIpAddrDelEvt(uint32_t);
+ void HandleNeighIpAddrAddEvt(ipacm_event_data_all *);
+ void HandleNeighIpAddrDelEvt(uint32_t);
+ void HandleSTAClientAddEvt(uint32_t);
+ void HandleSTAClientDelEvt(uint32_t);
};
extern IPACM_ConntrackListener *CtList;
diff --git a/ipacm/inc/IPACM_Conntrack_NATApp.h b/ipacm/inc/IPACM_Conntrack_NATApp.h
index 9eb9b4f..7c97225 100644
--- a/ipacm/inc/IPACM_Conntrack_NATApp.h
+++ b/ipacm/inc/IPACM_Conntrack_NATApp.h
@@ -112,7 +112,8 @@
int UpdatePwrSaveIf(uint32_t);
int ResetPwrSaveIf(uint32_t);
- int DelEntriesOnClntDiscon(uint32_t);
+ int DelEntriesOnClntDiscon(uint32_t);
+ int DelEntriesOnSTAClntDiscon(uint32_t);
void UpdateTcpUdpTo(uint32_t, int proto);
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index 0daf100..d225f4c 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -107,6 +107,7 @@
#define IPACM_INVALID_INDEX (ipa_ip_type)0xFF
#define IPA_MAX_NUM_WIFI_CLIENTS 32
+#define IPA_MAX_NUM_WAN_CLIENTS 10
#define IPA_MAX_NUM_ETH_CLIENTS 15
#define IPA_MAX_NUM_AMPDU_RULE 15
#define IPA_MAC_ADDR_SIZE 6
diff --git a/ipacm/inc/IPACM_Wan.h b/ipacm/inc/IPACM_Wan.h
index 5ef11f2..7923316 100644
--- a/ipacm/inc/IPACM_Wan.h
+++ b/ipacm/inc/IPACM_Wan.h
@@ -53,6 +53,31 @@
#define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4 2
#define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6 3
+typedef struct _wan_client_rt_hdl
+{
+ uint32_t wan_rt_rule_hdl_v4;
+ uint32_t wan_rt_rule_hdl_v6[IPV6_NUM_ADDR];
+ uint32_t wan_rt_rule_hdl_v6_wan[IPV6_NUM_ADDR];
+}wan_client_rt_hdl;
+
+typedef struct _ipa_wan_client
+{
+ ipacm_event_data_wlan_ex* p_hdr_info;
+ uint8_t mac[IPA_MAC_ADDR_SIZE];
+ uint32_t v4_addr;
+ uint32_t v6_addr[IPV6_NUM_ADDR][4];
+ uint32_t hdr_hdl_v4;
+ uint32_t hdr_hdl_v6;
+ bool route_rule_set_v4;
+ int route_rule_set_v6;
+ bool ipv4_set;
+ int ipv6_set;
+ bool ipv4_header_set;
+ bool ipv6_header_set;
+ bool power_save_set;
+ wan_client_rt_hdl wan_rt_hdl[0]; /* depends on number of tx properties */
+}ipa_wan_client;
+
/* wan iface */
class IPACM_Wan : public IPACM_Iface
{
@@ -125,6 +150,119 @@
/* IPACM firewall Configuration file*/
IPACM_firewall_conf_t firewall_config;
+ /* STA mode wan-client*/
+ int wan_client_len;
+ ipa_wan_client *wan_client;
+ int header_name_count;
+ int num_wan_client;
+ uint8_t invalid_mac[IPA_MAC_ADDR_SIZE];
+
+ inline ipa_wan_client* get_client_memptr(ipa_wan_client *param, int cnt)
+ {
+ char *ret = ((char *)param) + (wan_client_len * cnt);
+ return (ipa_wan_client *)ret;
+ }
+
+ inline int get_wan_client_index(uint8_t *mac_addr)
+ {
+ int cnt;
+ int num_wan_client_tmp = num_wan_client;
+
+ IPACMDBG_H("Passed 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]);
+
+ for(cnt = 0; cnt < num_wan_client_tmp; cnt++)
+ {
+ IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ get_client_memptr(wan_client, cnt)->mac[0],
+ get_client_memptr(wan_client, cnt)->mac[1],
+ get_client_memptr(wan_client, cnt)->mac[2],
+ get_client_memptr(wan_client, cnt)->mac[3],
+ get_client_memptr(wan_client, cnt)->mac[4],
+ get_client_memptr(wan_client, cnt)->mac[5]);
+
+ if(memcmp(get_client_memptr(wan_client, cnt)->mac,
+ mac_addr,
+ sizeof(get_client_memptr(wan_client, cnt)->mac)) == 0)
+ {
+ IPACMDBG_H("Matched client index: %d\n", cnt);
+ return cnt;
+ }
+ }
+
+ return IPACM_INVALID_INDEX;
+ }
+
+ inline int delete_wan_rtrules(int clt_indx, ipa_ip_type iptype)
+ {
+ uint32_t tx_index;
+ uint32_t rt_hdl;
+ int num_v6;
+
+ if(iptype == IPA_IP_v4)
+ {
+ for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
+ {
+ if((tx_prop->tx[tx_index].ip == IPA_IP_v4) && (get_client_memptr(wan_client, clt_indx)->route_rule_set_v4==true)) /* for ipv4 */
+ {
+ IPACMDBG_H("Delete client index %d ipv4 Qos rules for tx:%d \n",clt_indx,tx_index);
+ rt_hdl = get_client_memptr(wan_client, clt_indx)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4;
+
+ if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v4) == false)
+ {
+ return IPACM_FAILURE;
+ }
+ }
+ } /* end of for loop */
+
+ /* clean the 4 Qos ipv4 RT rules for client:clt_indx */
+ if(get_client_memptr(wan_client, clt_indx)->route_rule_set_v4==true) /* for ipv4 */
+ {
+ get_client_memptr(wan_client, clt_indx)->route_rule_set_v4 = false;
+ }
+ }
+
+ if(iptype == IPA_IP_v6)
+ {
+ for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
+ {
+
+ if((tx_prop->tx[tx_index].ip == IPA_IP_v6) && (get_client_memptr(wan_client, clt_indx)->route_rule_set_v6 != 0)) /* for ipv6 */
+ {
+ for(num_v6 =0;num_v6 < get_client_memptr(wan_client, clt_indx)->route_rule_set_v6;num_v6++)
+ {
+ IPACMDBG_H("Delete client index %d ipv6 Qos rules for %d-st ipv6 for tx:%d\n", clt_indx,num_v6,tx_index);
+ rt_hdl = get_client_memptr(wan_client, clt_indx)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6[num_v6];
+ if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false)
+ {
+ return IPACM_FAILURE;
+ }
+
+ rt_hdl = get_client_memptr(wan_client, clt_indx)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[num_v6];
+ if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false)
+ {
+ return IPACM_FAILURE;
+ }
+ }
+
+ }
+ } /* end of for loop */
+
+ /* clean the 4 Qos ipv6 RT rules for client:clt_indx */
+ if(get_client_memptr(wan_client, clt_indx)->route_rule_set_v6 != 0) /* for ipv6 */
+ {
+ get_client_memptr(wan_client, clt_indx)->route_rule_set_v6 = 0;
+ }
+ }
+
+ return IPACM_SUCCESS;
+ }
+
+ int handle_wan_hdr_init(uint8_t *mac_addr);
+ int handle_wan_client_ipaddr(ipacm_event_data_all *data);
+ int handle_wan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype);
+
/* handle new_address event */
int handle_addr_evt(ipacm_event_data_addr *data);
diff --git a/ipacm/src/IPACM_ConntrackListener.cpp b/ipacm/src/IPACM_ConntrackListener.cpp
index 3559a8c..3a2041a 100644
--- a/ipacm/src/IPACM_ConntrackListener.cpp
+++ b/ipacm/src/IPACM_ConntrackListener.cpp
@@ -44,11 +44,13 @@
nat_inst = NatApp::GetInstance();
NatIfaceCnt = 0;
+ StaClntCnt = 0;
pNatIfaces = NULL;
pConfig = NULL;
memset(nat_iface_ipv4_addr, 0, sizeof(nat_iface_ipv4_addr));
memset(nonnat_iface_ipv4_addr, 0, sizeof(nonnat_iface_ipv4_addr));
+ memset(sta_clnt_ipv4_addr, 0, sizeof(sta_clnt_ipv4_addr));
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, this);
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, this);
@@ -857,12 +859,46 @@
goto IGNORE;
}
- IPACMDBG("For embedded connections add dummy nat rule\n");
- IPACMDBG("Change private port %d to %d\n",
- rule.private_port, rule.public_port);
- rule.private_port = rule.public_port;
+ IPACMDBG("For embedded connections add dummy nat rule\n");
+ IPACMDBG("Change private port %d to %d\n",
+ rule.private_port, rule.public_port);
+ rule.private_port = rule.public_port;
}
+ /* Check whether target is in STA client list or not
+ if not ignore the connection */
+ int nCnt;
+
+ if(!isStaMode || (StaClntCnt == 0))
+ {
+ goto ADD;
+ }
+
+ if((sta_clnt_ipv4_addr[0] & 0xFFFFFF00) !=
+ (rule.target_ip & 0xFFFFFF00))
+ {
+ IPACMDBG("STA client subnet mask not matching\n");
+ goto ADD;
+ }
+
+ IPACMDBG("StaClntCnt %d\n", StaClntCnt);
+ for(nCnt = 0; nCnt < StaClntCnt; nCnt++)
+ {
+ IPACMDBG("Comparing trgt_ip 0x%x with sta clnt ip: 0x%x\n",
+ rule.target_ip, sta_clnt_ipv4_addr[nCnt]);
+ if(rule.target_ip == sta_clnt_ipv4_addr[nCnt])
+ {
+ IPACMDBG("Match index %d\n", nCnt);
+ goto ADD;
+ }
+ }
+
+ IPACMDBG("Not matching with STA Clnt Ip Addrs 0x%x\n",
+ rule.target_ip);
+ goto IGNORE;
+
+
+ADD:
IPACMDBG("Nat Entry with below information will either be added or deleted\n");
iptodot("target ip or dst ip", rule.target_ip);
IPACMDBG("target port or dst port: 0x%x Decimal:%d\n", rule.target_port, rule.target_port);
@@ -963,8 +999,60 @@
return;
}
+void IPACM_ConntrackListener::HandleSTAClientAddEvt(uint32_t clnt_ip_addr)
+{
+ int cnt;
+ IPACMDBG("Received STA client 0x%x\n", clnt_ip_addr);
+ if(StaClntCnt >= MAX_STA_CLNT_IFACES)
+ {
+ IPACMDBG("Max STA client reached, ignore 0x%x\n", clnt_ip_addr);
+ return;
+ }
+ for(cnt=0; cnt<MAX_STA_CLNT_IFACES; cnt++)
+ {
+ if(sta_clnt_ipv4_addr[cnt] != 0 &&
+ sta_clnt_ipv4_addr[cnt] == clnt_ip_addr)
+ {
+ IPACMDBG("Ignoring duplicate one 0x%x\n", clnt_ip_addr);
+ break;
+ }
+ if(sta_clnt_ipv4_addr[cnt] == 0)
+ {
+ IPACMDBG("Adding STA client 0x%x at Index: %d\n",
+ clnt_ip_addr, cnt);
+ sta_clnt_ipv4_addr[cnt] = clnt_ip_addr;
+ StaClntCnt++;
+ IPACMDBG("STA client cnt %d\n", StaClntCnt);
+ break;
+ }
+ }
+ return;
+}
+
+void IPACM_ConntrackListener::HandleSTAClientDelEvt(uint32_t clnt_ip_addr)
+{
+ int cnt;
+ IPACMDBG("Received STA client 0x%x\n", clnt_ip_addr);
+
+ for(cnt=0; cnt<MAX_STA_CLNT_IFACES; cnt++)
+ {
+ if(sta_clnt_ipv4_addr[cnt] != 0 &&
+ sta_clnt_ipv4_addr[cnt] == clnt_ip_addr)
+ {
+ IPACMDBG("Deleting STA client 0x%x at index: %d\n",
+ clnt_ip_addr, cnt);
+ sta_clnt_ipv4_addr[cnt] = 0;
+ nat_inst->DelEntriesOnSTAClntDiscon(clnt_ip_addr);
+ StaClntCnt--;
+ IPACMDBG("STA client cnt %d\n", StaClntCnt);
+ break;
+ }
+ }
+
+ return;
+}
diff --git a/ipacm/src/IPACM_Conntrack_NATApp.cpp b/ipacm/src/IPACM_Conntrack_NATApp.cpp
index b55d7e9..3d388f9 100644
--- a/ipacm/src/IPACM_Conntrack_NATApp.cpp
+++ b/ipacm/src/IPACM_Conntrack_NATApp.cpp
@@ -760,3 +760,38 @@
IPACMDBG("Deleted %d entries\n", (tmp - curCnt));
return 0;
}
+
+int NatApp::DelEntriesOnSTAClntDiscon(uint32_t ip_addr)
+{
+ int cnt, tmp = curCnt;
+ IPACMDBG("Received IP address: 0x%x\n", ip_addr);
+
+ if(ip_addr == INVALID_IP_ADDR)
+ {
+ IPACMERR("Invalid ip address received\n");
+ return -1;
+ }
+
+ CHK_TBL_HDL();
+
+ for(cnt = 0; cnt < max_entries; cnt++)
+ {
+ if(cache[cnt].target_ip == ip_addr)
+ {
+ if(cache[cnt].enabled == true)
+ {
+ if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0)
+ {
+ IPACMERR("unable to delete the rule\n");
+ continue;
+ }
+ }
+
+ memset(&cache[cnt], 0, sizeof(cache[cnt]));
+ curCnt--;
+ }
+ }
+
+ IPACMDBG("Deleted %d entries\n", (tmp - curCnt));
+ return 0;
+}
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
index c685ba5..1791cee 100644
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.cpp
@@ -48,6 +48,7 @@
#include "linux/rmnet_ipa_fd_ioctl.h"
#include "IPACM_Config.h"
#include "IPACM_Defs.h"
+#include <IPACM_ConntrackListener.h>
bool IPACM_Wan::wan_up = false;
bool IPACM_Wan::wan_up_v6 = false;
@@ -93,6 +94,22 @@
memset(ipv6_prefix, 0, sizeof(ipv6_prefix));
ext_prop = NULL;
+ num_wan_client = 0;
+ header_name_count = 0;
+ memset(invalid_mac, 0, sizeof(invalid_mac));
+ if(iface_query != NULL)
+ {
+ wan_client_len = (sizeof(ipa_wan_client)) + (iface_query->num_tx_props * sizeof(wan_client_rt_hdl));
+ wan_client = (ipa_wan_client *)calloc(IPA_MAX_NUM_WAN_CLIENTS, wan_client_len);
+ if (wan_client == NULL)
+ {
+ IPACMERR("unable to allocate memory\n");
+ return;
+ }
+ IPACMDBG_H("index:%d constructor: Tx properties:%d\n", iface_index, iface_query->num_tx_props);
+ }
+
+
if(m_is_sta_mode == Q6_WAN)
{
IPACMDBG_H("The new WAN interface is modem.\n");
@@ -689,10 +706,35 @@
{
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_H("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT in STA mode\n");
handle_header_add_evt(data->mac_addr);
+
+ /* new */
+ IPACMDBG_H("wan-iface got client \n");
+ /* first construc WAN-client full header */
+ if(memcmp(data->mac_addr,
+ invalid_mac,
+ sizeof(data->mac_addr)) == 0)
+ {
+ IPACMDBG_H("Received invalid Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ data->mac_addr[0], data->mac_addr[1], data->mac_addr[2],
+ data->mac_addr[3], data->mac_addr[4], data->mac_addr[5]);
+ return;
+ }
+
+ handle_wan_hdr_init(data->mac_addr);
+ IPACMDBG_H("construct wan header and route rules \n");
+ /* Associate with IP and construct RT-rule */
+ if (handle_wan_client_ipaddr(data) == IPACM_FAILURE)
+ {
+ return;
+ }
+ handle_wan_client_route_rule(data->mac_addr, data->iptype);
+ return;
+
}
}
break;
@@ -1136,8 +1178,8 @@
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))
- {
+ if((header_set_v4 == true) || (header_set_v6 == true))
+ {
IPACMDBG_H("Already add STA full header\n");
return IPACM_SUCCESS;
}
@@ -3430,6 +3472,59 @@
IPACMDBG_H("finished delete default v6 RT rules\n ");
}
+
+ /* clean wan-client header, routing rules */
+ IPACMDBG_H("left %d wan clients need to be deleted \n ", num_wan_client);
+ for (i = 0; i < num_wan_client; i++)
+ {
+ /* Del NAT rules before ipv4 RT rules are delete */
+ if(get_client_memptr(wan_client, i)->ipv4_set == true)
+ {
+ IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wan_client, i)->v4_addr);
+ CtList->HandleSTAClientDelEvt(get_client_memptr(wan_client, i)->v4_addr);
+ }
+
+ if (delete_wan_rtrules(i, IPA_IP_v4))
+ {
+ IPACMERR("unbale to delete wan-client v4 route rules for index %d\n", i);
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+
+ if (delete_wan_rtrules(i, IPA_IP_v6))
+ {
+ IPACMERR("unbale to delete ecm-client v6 route rules for index %d\n", i);
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+
+ IPACMDBG_H("Delete %d client header\n", num_wan_client);
+
+
+ if(get_client_memptr(wan_client, i)->ipv4_header_set == true)
+ {
+ if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, i)->hdr_hdl_v4)
+ == false)
+ {
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ }
+
+ if(get_client_memptr(wan_client, i)->ipv6_header_set == true)
+ {
+ if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, i)->hdr_hdl_v6)
+ == false)
+ {
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+ }
+ } /* end of for loop */
+
+ /* free the edm clients cache */
+ IPACMDBG_H("Free wan clients cache\n");
+
/* check software routing fl rule hdl */
if (softwarerouting_act == true)
{
@@ -3518,7 +3613,10 @@
{
free(wan_route_rule_v6_hdl_a5);
}
-
+ if (wan_client != NULL)
+ {
+ free(wan_client);
+ }
close(m_fd_ipa);
return res;
}
@@ -3705,7 +3803,10 @@
{
free(wan_route_rule_v6_hdl_a5);
}
-
+ if (wan_client != NULL)
+ {
+ free(wan_client);
+ }
close(m_fd_ipa);
return res;
}
@@ -3969,3 +4070,552 @@
}
}
+/* handle STA WAN-client */
+/* handle WAN client initial, construct full headers (tx property) */
+int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr)
+{
+
+#define WAN_IFACE_INDEX_LEN 2
+
+ 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;
+ uint32_t cnt;
+ int clnt_indx;
+
+ clnt_indx = get_wan_client_index(mac_addr);
+
+ if (clnt_indx != IPACM_INVALID_INDEX)
+ {
+ IPACMERR("eth client is found/attached already with index %d \n", clnt_indx);
+ return IPACM_FAILURE;
+ }
+
+ /* add header to IPA */
+ if (num_wan_client >= IPA_MAX_NUM_WAN_CLIENTS)
+ {
+ IPACMERR("Reached maximum number(%d) of eth clients\n", IPA_MAX_NUM_WAN_CLIENTS);
+ return IPACM_FAILURE;
+ }
+
+ IPACMDBG_H("WAN client number: %d\n", num_wan_client);
+
+ memcpy(get_client_memptr(wan_client, num_wan_client)->mac,
+ mac_addr,
+ sizeof(get_client_memptr(wan_client, num_wan_client)->mac));
+
+
+ IPACMDBG_H("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]);
+
+ IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ get_client_memptr(wan_client, num_wan_client)->mac[0],
+ get_client_memptr(wan_client, num_wan_client)->mac[1],
+ get_client_memptr(wan_client, num_wan_client)->mac[2],
+ get_client_memptr(wan_client, num_wan_client)->mac[3],
+ get_client_memptr(wan_client, num_wan_client)->mac[4],
+ get_client_memptr(wan_client, num_wan_client)->mac[5]);
+
+ /* add header to IPA */
+ if(tx_prop != NULL)
+ {
+ 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)
+ {
+ IPACMDBG_H("Got partial v4-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_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt);
+ if (m_header.CopyHeader(&sCopyHeader) == false)
+ {
+ PERROR("ioctl copy header failed");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+
+ IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
+ IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst);
+ 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;
+ }
+
+ snprintf(index,sizeof(index), "%d", header_name_count);
+ if (strlcat(pHeaderDescriptor->hdr[0].name, index, 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;
+ }
+
+ get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl;
+ IPACMDBG_H("eth-client(%d) v4 full header name:%s header handle:(0x%x)\n",
+ num_wan_client,
+ pHeaderDescriptor->hdr[0].name,
+ get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v4);
+ get_client_memptr(wan_client, num_wan_client)->ipv4_header_set=true;
+
+ 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_H("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_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt);
+ if (m_header.CopyHeader(&sCopyHeader) == false)
+ {
+ PERROR("ioctl copy header failed");
+ res = IPACM_FAILURE;
+ goto fail;
+ }
+
+ IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
+ IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst);
+ 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;
+ }
+ snprintf(index,sizeof(index), "%d", header_name_count);
+ if (strlcat(pHeaderDescriptor->hdr[0].name, index, 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;
+ }
+
+ get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl;
+ IPACMDBG_H("eth-client(%d) v6 full header name:%s header handle:(0x%x)\n",
+ num_wan_client,
+ pHeaderDescriptor->hdr[0].name,
+ get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v6);
+
+ get_client_memptr(wan_client, num_wan_client)->ipv6_header_set=true;
+
+ break;
+
+ }
+ }
+ /* initialize wifi client*/
+ get_client_memptr(wan_client, num_wan_client)->route_rule_set_v4 = false;
+ get_client_memptr(wan_client, num_wan_client)->route_rule_set_v6 = 0;
+ get_client_memptr(wan_client, num_wan_client)->ipv4_set = false;
+ get_client_memptr(wan_client, num_wan_client)->ipv6_set = 0;
+ num_wan_client++;
+ header_name_count++; //keep increasing header_name_count
+ res = IPACM_SUCCESS;
+ IPACMDBG_H("eth client number: %d\n", num_wan_client);
+ }
+ else
+ {
+ return res;
+ }
+fail:
+ free(pHeaderDescriptor);
+
+ return res;
+}
+
+/*handle eth client */
+int IPACM_Wan::handle_wan_client_ipaddr(ipacm_event_data_all *data)
+{
+ int clnt_indx;
+ int v6_num;
+
+ IPACMDBG_H("number of wan clients: %d\n", num_wan_client);
+ IPACMDBG_H(" event MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ data->mac_addr[0],
+ data->mac_addr[1],
+ data->mac_addr[2],
+ data->mac_addr[3],
+ data->mac_addr[4],
+ data->mac_addr[5]);
+
+ clnt_indx = get_wan_client_index(data->mac_addr);
+
+ if (clnt_indx == IPACM_INVALID_INDEX)
+ {
+ IPACMERR("wan client not found/attached \n");
+ return IPACM_FAILURE;
+ }
+
+ IPACMDBG_H("Ip-type received %d\n", data->iptype);
+ if (data->iptype == IPA_IP_v4)
+ {
+ IPACMDBG_H("ipv4 address: 0x%x\n", data->ipv4_addr);
+ if (data->ipv4_addr != 0) /* not 0.0.0.0 */
+ {
+ if (get_client_memptr(wan_client, clnt_indx)->ipv4_set == false)
+ {
+ get_client_memptr(wan_client, clnt_indx)->v4_addr = data->ipv4_addr;
+ get_client_memptr(wan_client, clnt_indx)->ipv4_set = true;
+ /* Add NAT rules after ipv4 RT rules are set */
+ CtList->HandleSTAClientAddEvt(data->ipv4_addr);
+ }
+ else
+ {
+ /* check if client got new IPv4 address*/
+ if(data->ipv4_addr == get_client_memptr(wan_client, clnt_indx)->v4_addr)
+ {
+ IPACMDBG_H("Already setup ipv4 addr for client:%d, ipv4 address didn't change\n", clnt_indx);
+ return IPACM_FAILURE;
+ }
+ else
+ {
+ IPACMDBG_H("ipv4 addr for client:%d is changed \n", clnt_indx);
+ /* Del NAT rules before ipv4 RT rules are delete */
+ CtList->HandleSTAClientDelEvt(get_client_memptr(wan_client, clnt_indx)->v4_addr);
+ delete_wan_rtrules(clnt_indx,IPA_IP_v4);
+ get_client_memptr(wan_client, clnt_indx)->route_rule_set_v4 = false;
+ get_client_memptr(wan_client, clnt_indx)->v4_addr = data->ipv4_addr;
+ /* Add NAT rules after ipv4 RT rules are set */
+ CtList->HandleSTAClientAddEvt(data->ipv4_addr);
+ }
+ }
+ }
+ else
+ {
+ IPACMDBG_H("Invalid client IPv4 address \n");
+ return IPACM_FAILURE;
+ }
+ }
+ else
+ {
+ if ((data->ipv6_addr[0] != 0) || (data->ipv6_addr[1] != 0) ||
+ (data->ipv6_addr[2] != 0) || (data->ipv6_addr[3] || 0)) /* check if all 0 not valid ipv6 address */
+ {
+ IPACMDBG_H("ipv6 address: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]);
+ if(get_client_memptr(wan_client, clnt_indx)->ipv6_set < IPV6_NUM_ADDR)
+ {
+
+ for(v6_num=0;v6_num < get_client_memptr(wan_client, clnt_indx)->ipv6_set;v6_num++)
+ {
+ if( data->ipv6_addr[0] == get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][0] &&
+ data->ipv6_addr[1] == get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][1] &&
+ data->ipv6_addr[2]== get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][2] &&
+ data->ipv6_addr[3] == get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][3])
+ {
+ IPACMDBG_H("Already see this ipv6 addr for client:%d\n", clnt_indx);
+ return IPACM_FAILURE; /* not setup the RT rules*/
+ break;
+ }
+ }
+
+ /* not see this ipv6 before for wifi client*/
+ get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][0] = data->ipv6_addr[0];
+ get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][1] = data->ipv6_addr[1];
+ get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][2] = data->ipv6_addr[2];
+ get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][3] = data->ipv6_addr[3];
+ get_client_memptr(wan_client, clnt_indx)->ipv6_set++;
+ }
+ else
+ {
+ IPACMDBG_H("Already got 3 ipv6 addr for client:%d\n", clnt_indx);
+ return IPACM_FAILURE; /* not setup the RT rules*/
+ }
+ }
+ }
+
+ return IPACM_SUCCESS;
+}
+
+/*handle wan client routing rule*/
+int IPACM_Wan::handle_wan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype)
+{
+ struct ipa_ioc_add_rt_rule *rt_rule;
+ struct ipa_rt_rule_add *rt_rule_entry;
+ uint32_t tx_index;
+ int wan_index,v6_num;
+ const int NUM = 1;
+
+ if(tx_prop == NULL)
+ {
+ IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
+ return IPACM_SUCCESS;
+ }
+
+ IPACMDBG_H("Received mac_addr 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]);
+
+ wan_index = get_wan_client_index(mac_addr);
+ if (wan_index == IPACM_INVALID_INDEX)
+ {
+ IPACMDBG_H("wan client not found/attached \n");
+ return IPACM_SUCCESS;
+ }
+
+ if (iptype==IPA_IP_v4) {
+ IPACMDBG_H("wan client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", wan_index, iptype,
+ get_client_memptr(wan_client, wan_index)->ipv4_set,
+ get_client_memptr(wan_client, wan_index)->route_rule_set_v4);
+ } else {
+ IPACMDBG_H("wan client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", wan_index, iptype,
+ get_client_memptr(wan_client, wan_index)->ipv6_set,
+ get_client_memptr(wan_client, wan_index)->route_rule_set_v6);
+ }
+
+ /* Add default routing rules if not set yet */
+ if ((iptype == IPA_IP_v4
+ && get_client_memptr(wan_client, wan_index)->route_rule_set_v4 == false
+ && get_client_memptr(wan_client, wan_index)->ipv4_set == true)
+ || (iptype == IPA_IP_v6
+ && get_client_memptr(wan_client, wan_index)->route_rule_set_v6 < get_client_memptr(wan_client, wan_index)->ipv6_set
+ ))
+ {
+
+ /* 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);
+
+ 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 == NULL)
+ {
+ PERROR("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;
+
+ for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
+ {
+ if(iptype != tx_prop->tx[tx_index].ip)
+ {
+ IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n",
+ tx_index, tx_prop->tx[tx_index].ip,iptype);
+ continue;
+ }
+
+ rt_rule_entry = &rt_rule->rules[0];
+ rt_rule_entry->at_rear = 0;
+
+ if (iptype == IPA_IP_v4)
+ {
+ IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", wan_index,
+ get_client_memptr(wan_client, wan_index)->v4_addr);
+
+ IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n",
+ wan_index,
+ get_client_memptr(wan_client, wan_index)->hdr_hdl_v4);
+ strncpy(rt_rule->rt_tbl_name,
+ IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name,
+ sizeof(rt_rule->rt_tbl_name));
+
+ rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
+ memcpy(&rt_rule_entry->rule.attrib,
+ &tx_prop->tx[tx_index].attrib,
+ sizeof(rt_rule_entry->rule.attrib));
+ rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
+ rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, wan_index)->hdr_hdl_v4;
+ rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wan_client, wan_index)->v4_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");
+ free(rt_rule);
+ return IPACM_FAILURE;
+ }
+
+ /* copy ipv4 RT hdl */
+ get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4 =
+ rt_rule->rules[0].rt_rule_hdl;
+ IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index,
+ get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4, iptype);
+ } else {
+
+ for(v6_num = get_client_memptr(wan_client, wan_index)->route_rule_set_v6;v6_num < get_client_memptr(wan_client, wan_index)->ipv6_set;v6_num++)
+ {
+ IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n",
+ wan_index,
+ get_client_memptr(wan_client, wan_index)->hdr_hdl_v6);
+
+ /* v6 LAN_RT_TBL */
+ strncpy(rt_rule->rt_tbl_name,
+ IPACM_Iface::ipacmcfg->rt_tbl_v6.name,
+ sizeof(rt_rule->rt_tbl_name));
+
+ /* Support QCMAP LAN traffic feature, send to A5 */
+ rt_rule_entry->rule.dst = iface_query->excp_pipe;
+ memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib));
+ rt_rule_entry->rule.hdr_hdl = 0;
+ rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
+ rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][0];
+ rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][1];
+ rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][2];
+ rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][3];
+ rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
+ rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
+ rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
+ rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
+
+ if (false == m_routing.AddRoutingRule(rt_rule))
+ {
+ IPACMERR("Routing rule addition failed!\n");
+ free(rt_rule);
+ return IPACM_FAILURE;
+ }
+
+ get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6[v6_num] = rt_rule->rules[0].rt_rule_hdl;
+ IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index,
+ get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6[v6_num], iptype);
+
+ /*Copy same rule to v6 WAN RT TBL*/
+ strncpy(rt_rule->rt_tbl_name,
+ IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name,
+ sizeof(rt_rule->rt_tbl_name));
+
+ /* Downlink traffic from Wan iface, directly through IPA */
+ rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
+ memcpy(&rt_rule_entry->rule.attrib,
+ &tx_prop->tx[tx_index].attrib,
+ sizeof(rt_rule_entry->rule.attrib));
+ rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, wan_index)->hdr_hdl_v6;
+ rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
+ rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][0];
+ rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][1];
+ rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][2];
+ rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][3];
+ rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
+ rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
+ rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
+ rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
+
+ if (false == m_routing.AddRoutingRule(rt_rule))
+ {
+ IPACMERR("Routing rule addition failed!\n");
+ free(rt_rule);
+ return IPACM_FAILURE;
+ }
+
+ get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num] = rt_rule->rules[0].rt_rule_hdl;
+ IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index,
+ get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num], iptype);
+ }
+ }
+
+ } /* end of for loop */
+
+ free(rt_rule);
+
+ if (iptype == IPA_IP_v4)
+ {
+ get_client_memptr(wan_client, wan_index)->route_rule_set_v4 = true;
+ }
+ else
+ {
+ get_client_memptr(wan_client, wan_index)->route_rule_set_v6 = get_client_memptr(wan_client, wan_index)->ipv6_set;
+ }
+ }
+
+ return IPACM_SUCCESS;
+}