diff options
author | Bruno Martins <bgcngm@gmail.com> | 2018-01-08 12:51:07 +0000 |
---|---|---|
committer | Davide Garberi <dade.garberi@gmail.com> | 2018-01-20 09:30:21 +0100 |
commit | 1c67f47d4a205e12650dcb6255c00bafc0046082 (patch) | |
tree | 72bb48ca2152cb2295b0f8de39497490d8616f6f /data-ipa-cfg-mgr/ipacm/src/IPACM_Conntrack_NATApp.cpp | |
parent | 6b0c862328f58e523e2a6efa667a2f4b3a609bf3 (diff) |
msm8996-common: Import IPACM back
* QC package: LA.UM.6.5.r1-05300-8x96.0
* Squashed with commits 08e2a5b9b, 055b183 and 8fcf57b
Change-Id: I2f7a792dc0155986e065d1bf79e1f08370c3d79c
Signed-off-by: Davide Garberi <dade.garberi@gmail.com>
Diffstat (limited to 'data-ipa-cfg-mgr/ipacm/src/IPACM_Conntrack_NATApp.cpp')
-rw-r--r-- | data-ipa-cfg-mgr/ipacm/src/IPACM_Conntrack_NATApp.cpp | 1022 |
1 files changed, 1022 insertions, 0 deletions
diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Conntrack_NATApp.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Conntrack_NATApp.cpp new file mode 100644 index 0000000..c13c48e --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Conntrack_NATApp.cpp @@ -0,0 +1,1022 @@ +/* +Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#include "IPACM_Conntrack_NATApp.h" +#include "IPACM_ConntrackClient.h" +#ifdef FEATURE_IPACM_HAL +#include "IPACM_OffloadManager.h" +#endif + +#define INVALID_IP_ADDR 0x0 + +/* NatApp class Implementation */ +NatApp *NatApp::pInstance = NULL; +NatApp::NatApp() +{ + max_entries = 0; + cache = NULL; + + nat_table_hdl = 0; + pub_ip_addr = 0; + + curCnt = 0; + + pALGPorts = NULL; + nALGPort = 0; + + ct = NULL; + ct_hdl = NULL; + + memset(temp, 0, sizeof(temp)); +} + +int NatApp::Init(void) +{ + IPACM_Config *pConfig; + int size = 0; + + pConfig = IPACM_Config::GetInstance(); + if(pConfig == NULL) + { + IPACMERR("Unable to get Config instance\n"); + return -1; + } + + max_entries = pConfig->GetNatMaxEntries(); + + size = (sizeof(nat_table_entry) * max_entries); + cache = (nat_table_entry *)malloc(size); + if(cache == NULL) + { + IPACMERR("Unable to allocate memory for cache\n"); + goto fail; + } + IPACMDBG("Allocated %d bytes for config manager nat cache\n", size); + memset(cache, 0, size); + + nALGPort = pConfig->GetAlgPortCnt(); + if(nALGPort > 0) + { + pALGPorts = (ipacm_alg *)malloc(sizeof(ipacm_alg) * nALGPort); + if(pALGPorts == NULL) + { + IPACMERR("Unable to allocate memory for alg prots\n"); + goto fail; + } + memset(pALGPorts, 0, sizeof(ipacm_alg) * nALGPort); + + if(pConfig->GetAlgPorts(nALGPort, pALGPorts) != 0) + { + IPACMERR("Unable to retrieve ALG prots\n"); + goto fail; + } + + IPACMDBG("Printing %d alg ports information\n", nALGPort); + for(int cnt=0; cnt<nALGPort; cnt++) + { + IPACMDBG("%d: Proto[%d], port[%d]\n", cnt, pALGPorts[cnt].protocol, pALGPorts[cnt].port); + } + } + + return 0; + +fail: + free(cache); + free(pALGPorts); + return -1; +} + +NatApp* NatApp::GetInstance() +{ + if(pInstance == NULL) + { + pInstance = new NatApp(); + + if(pInstance->Init()) + { + delete pInstance; + return NULL; + } + } + + return pInstance; +} + +/* NAT APP related object function definitions */ + +int NatApp::AddTable(uint32_t pub_ip) +{ + int ret; + int cnt = 0; + ipa_nat_ipv4_rule nat_rule; + IPACMDBG_H("%s() %d\n", __FUNCTION__, __LINE__); + + /* Not reset the cache wait it timeout by destroy event */ +#if 0 + if (pub_ip != pub_ip_addr_pre) + { + IPACMDBG("Reset the cache because NAT-ipv4 different\n"); + memset(cache, 0, sizeof(nat_table_entry) * max_entries); + curCnt = 0; + } +#endif + ret = ipa_nat_add_ipv4_tbl(pub_ip, max_entries, &nat_table_hdl); + if(ret) + { + IPACMERR("unable to create nat table Error:%d\n", ret); + return ret; + } + + /* Add back the cached NAT-entry */ + if (pub_ip == pub_ip_addr_pre) + { + IPACMDBG("Restore the cache to ipa NAT-table\n"); + for(cnt = 0; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip !=0) + { + memset(&nat_rule, 0 , sizeof(nat_rule)); + nat_rule.private_ip = cache[cnt].private_ip; + nat_rule.target_ip = cache[cnt].target_ip; + nat_rule.target_port = cache[cnt].target_port; + nat_rule.private_port = cache[cnt].private_port; + nat_rule.public_port = cache[cnt].public_port; + nat_rule.protocol = cache[cnt].protocol; + + if(ipa_nat_add_ipv4_rule(nat_table_hdl, &nat_rule, &cache[cnt].rule_hdl) < 0) + { + IPACMERR("unable to add the rule delete from cache\n"); + memset(&cache[cnt], 0, sizeof(cache[cnt])); + curCnt--; + continue; + } + cache[cnt].enabled = true; + + IPACMDBG("On wan-iface reset added below rule successfully\n"); + iptodot("Private IP", nat_rule.private_ip); + iptodot("Target IP", nat_rule.target_ip); + IPACMDBG("Private Port:%d \t Target Port: %d\t", nat_rule.private_port, nat_rule.target_port); + IPACMDBG("Public Port:%d\n", nat_rule.public_port); + IPACMDBG("protocol: %d\n", nat_rule.protocol); + } + } + } + + pub_ip_addr = pub_ip; + return 0; +} + +void NatApp::Reset() +{ + int cnt = 0; + + nat_table_hdl = 0; + pub_ip_addr = 0; + /* NAT tbl deleted, reset enabled bit */ + for(cnt = 0; cnt < max_entries; cnt++) + { + cache[cnt].enabled = false; + } +} + +int NatApp::DeleteTable(uint32_t pub_ip) +{ + int ret; + IPACMDBG_H("%s() %d\n", __FUNCTION__, __LINE__); + + CHK_TBL_HDL(); + + if(pub_ip_addr != pub_ip) + { + IPACMDBG("Public ip address is not matching\n"); + IPACMERR("unable to delete the nat table\n"); + return -1; + } + + ret = ipa_nat_del_ipv4_tbl(nat_table_hdl); + if(ret) + { + IPACMERR("unable to delete nat table Error: %d\n", ret);; + return ret; + } + + pub_ip_addr_pre = pub_ip_addr; + Reset(); + return 0; +} + +/* Check for duplicate entries */ +bool NatApp::ChkForDup(const nat_table_entry *rule) +{ + int cnt = 0; + IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__); + + for(; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip == rule->private_ip && + cache[cnt].target_ip == rule->target_ip && + cache[cnt].private_port == rule->private_port && + cache[cnt].target_port == rule->target_port && + cache[cnt].protocol == rule->protocol) + { + log_nat(rule->protocol,rule->private_ip,rule->target_ip,rule->private_port,\ + rule->target_port,"Duplicate Rule\n"); + return true; + } + } + + return false; +} + +/* Delete the entry from Nat table on connection close */ +int NatApp::DeleteEntry(const nat_table_entry *rule) +{ + int cnt = 0; + IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__); + + log_nat(rule->protocol,rule->private_ip,rule->target_ip,rule->private_port,\ + rule->target_port,"for deletion\n"); + + + for(; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip == rule->private_ip && + cache[cnt].target_ip == rule->target_ip && + cache[cnt].private_port == rule->private_port && + cache[cnt].target_port == rule->target_port && + cache[cnt].protocol == rule->protocol) + { + + if(cache[cnt].enabled == true) + { + if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0) + { + IPACMERR("%s() %d deletion failed\n", __FUNCTION__, __LINE__); + } + + IPACMDBG_H("Deleted Nat entry(%d) Successfully\n", cnt); + } + else + { + IPACMDBG_H("Deleted Nat entry(%d) only from cache\n", cnt); + } + + memset(&cache[cnt], 0, sizeof(cache[cnt])); + curCnt--; + break; + } + } + + return 0; +} + +/* Add new entry to the nat table on new connection */ +int NatApp::AddEntry(const nat_table_entry *rule) +{ + int cnt = 0; + ipa_nat_ipv4_rule nat_rule; + + IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__); + + CHK_TBL_HDL(); + log_nat(rule->protocol,rule->private_ip,rule->target_ip,rule->private_port,\ + rule->target_port,"for addition\n"); + if(isAlgPort(rule->protocol, rule->private_port) || + isAlgPort(rule->protocol, rule->target_port)) + { + IPACMERR("connection using ALG Port, ignore\n"); + return -1; + } + + if(rule->private_ip == 0 || + rule->target_ip == 0 || + rule->private_port == 0 || + rule->target_port == 0 || + rule->protocol == 0) + { + IPACMERR("Invalid Connection, ignoring it\n"); + return 0; + } + + if(!ChkForDup(rule)) + { + for(; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip == 0 && + cache[cnt].target_ip == 0 && + cache[cnt].private_port == 0 && + cache[cnt].target_port == 0 && + cache[cnt].protocol == 0) + { + break; + } + } + + if(max_entries == cnt) + { + IPACMERR("Error: Unable to add, reached maximum rules\n"); + return -1; + } + else + { + memset(&nat_rule, 0, sizeof(nat_rule)); + nat_rule.private_ip = rule->private_ip; + nat_rule.target_ip = rule->target_ip; + nat_rule.target_port = rule->target_port; + nat_rule.private_port = rule->private_port; + nat_rule.public_port = rule->public_port; + nat_rule.protocol = rule->protocol; + + if(isPwrSaveIf(rule->private_ip) || + isPwrSaveIf(rule->target_ip)) + { + IPACMDBG("Device is Power Save mode: Dont insert into nat table but cache\n"); + cache[cnt].enabled = false; + cache[cnt].rule_hdl = 0; + } + else + { + + if(ipa_nat_add_ipv4_rule(nat_table_hdl, &nat_rule, &cache[cnt].rule_hdl) < 0) + { + IPACMERR("unable to add the rule\n"); + return -1; + } + + cache[cnt].enabled = true; + } + + cache[cnt].private_ip = rule->private_ip; + cache[cnt].target_ip = rule->target_ip; + cache[cnt].target_port = rule->target_port; + cache[cnt].private_port = rule->private_port; + cache[cnt].protocol = rule->protocol; + cache[cnt].timestamp = 0; + cache[cnt].public_port = rule->public_port; + cache[cnt].dst_nat = rule->dst_nat; + curCnt++; + } + + } + else + { + IPACMERR("Duplicate rule. Ignore it\n"); + return -1; + } + + if(cache[cnt].enabled == true) + { + IPACMDBG_H("Added rule(%d) successfully\n", cnt); + } + else + { + IPACMDBG_H("Cached rule(%d) successfully\n", cnt); + } + + return 0; +} + +void NatApp::UpdateCTUdpTs(nat_table_entry *rule, uint32_t new_ts) +{ +#ifdef FEATURE_IPACM_HAL + IOffloadManager::ConntrackTimeoutUpdater::natTimeoutUpdate_t entry; + IPACM_OffloadManager* OffloadMng; +#endif + iptodot("Private IP:", rule->private_ip); + iptodot("Target IP:", rule->target_ip); + IPACMDBG("Private Port: %d, Target Port: %d\n", rule->private_port, rule->target_port); + +#ifndef FEATURE_IPACM_HAL + int ret; + if(!ct_hdl) + { + ct_hdl = nfct_open(CONNTRACK, 0); + if(!ct_hdl) + { + PERROR("nfct_open"); + return; + } + } + + if(!ct) + { + ct = nfct_new(); + if(!ct) + { + PERROR("nfct_new"); + return; + } + } + + nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET); + if(rule->protocol == IPPROTO_UDP) + { + nfct_set_attr_u8(ct, ATTR_L4PROTO, rule->protocol); + nfct_set_attr_u32(ct, ATTR_TIMEOUT, udp_timeout); + } + else + { + nfct_set_attr_u8(ct, ATTR_L4PROTO, rule->protocol); + nfct_set_attr_u32(ct, ATTR_TIMEOUT, tcp_timeout); + } + + if(rule->dst_nat == false) + { + nfct_set_attr_u32(ct, ATTR_IPV4_SRC, htonl(rule->private_ip)); + nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(rule->private_port)); + + nfct_set_attr_u32(ct, ATTR_IPV4_DST, htonl(rule->target_ip)); + nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(rule->target_port)); + + IPACMDBG("dst nat is not set\n"); + } + else + { + nfct_set_attr_u32(ct, ATTR_IPV4_SRC, htonl(rule->target_ip)); + nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(rule->target_port)); + + nfct_set_attr_u32(ct, ATTR_IPV4_DST, htonl(pub_ip_addr)); + nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(rule->public_port)); + + IPACMDBG("dst nat is set\n"); + } + + iptodot("Source IP:", nfct_get_attr_u32(ct, ATTR_IPV4_SRC)); + iptodot("Destination IP:", nfct_get_attr_u32(ct, ATTR_IPV4_DST)); + IPACMDBG("Source Port: %d, Destination Port: %d\n", + nfct_get_attr_u16(ct, ATTR_PORT_SRC), nfct_get_attr_u16(ct, ATTR_PORT_DST)); + + IPACMDBG("updating %d connection with time: %d\n", + rule->protocol, nfct_get_attr_u32(ct, ATTR_TIMEOUT)); + + ret = nfct_query(ct_hdl, NFCT_Q_UPDATE, ct); + if(ret == -1) + { + IPACMERR("unable to update time stamp"); + DeleteEntry(rule); + } + else + { + rule->timestamp = new_ts; + IPACMDBG("Updated time stamp successfully\n"); + } +#else + if(rule->protocol == IPPROTO_UDP) + { + entry.proto = IOffloadManager::ConntrackTimeoutUpdater::UDP;; + } + else + { + entry.proto = IOffloadManager::ConntrackTimeoutUpdater::TCP; + } + + if(rule->dst_nat == false) + { + entry.src.ipAddr = htonl(rule->private_ip); + entry.src.port = rule->private_port; + entry.dst.ipAddr = htonl(rule->target_ip); + entry.dst.port = rule->target_port; + IPACMDBG("dst nat is not set\n"); + } + else + { + entry.src.ipAddr = htonl(rule->target_ip); + entry.src.port = rule->target_port; + entry.dst.ipAddr = htonl(pub_ip_addr); + entry.dst.port = rule->public_port; + IPACMDBG("dst nat is set\n"); + } + + iptodot("Source IP:", entry.src.ipAddr); + iptodot("Destination IP:", entry.dst.ipAddr); + IPACMDBG("Source Port: %d, Destination Port: %d\n", + entry.src.port, entry.dst.port); + + OffloadMng = IPACM_OffloadManager::GetInstance(); + if (OffloadMng->touInstance == NULL) { + IPACMERR("OffloadMng->touInstance is NULL, can't forward to framework!\n"); + } else { + OffloadMng->touInstance->updateTimeout(entry); + IPACMDBG("Updated time stamp successfully\n"); + rule->timestamp = new_ts; + } +#endif + return; +} + +void NatApp::UpdateUDPTimeStamp() +{ + int cnt; + uint32_t ts; + bool read_to = false; + + for(cnt = 0; cnt < max_entries; cnt++) + { + ts = 0; + if(cache[cnt].enabled == true && + (cache[cnt].private_ip != cache[cnt].public_ip)) + { + IPACMDBG("\n"); + if(ipa_nat_query_timestamp(nat_table_hdl, cache[cnt].rule_hdl, &ts) < 0) + { + IPACMERR("unable to retrieve timeout for rule hanle: %d\n", cache[cnt].rule_hdl); + continue; + } + + if(cache[cnt].timestamp == ts) + { + IPACMDBG("No Change in Time Stamp: cahce:%d, ipahw:%d\n", + cache[cnt].timestamp, ts); + continue; + } + + if (read_to == false) { + read_to = true; + Read_TcpUdp_Timeout(); + } + + UpdateCTUdpTs(&cache[cnt], ts); + } /* end of outer if */ + + } /* end of for loop */ + +} + +bool NatApp::isAlgPort(uint8_t proto, uint16_t port) +{ + int cnt; + for(cnt = 0; cnt < nALGPort; cnt++) + { + if(proto == pALGPorts[cnt].protocol && + port == pALGPorts[cnt].port) + { + return true; + } + } + + return false; +} + +bool NatApp::isPwrSaveIf(uint32_t ip_addr) +{ + int cnt; + + for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++) + { + if(0 != PwrSaveIfs[cnt] && + ip_addr == PwrSaveIfs[cnt]) + { + return true; + } + } + + return false; +} + +int NatApp::UpdatePwrSaveIf(uint32_t client_lan_ip) +{ + int cnt; + IPACMDBG_H("Received IP address: 0x%x\n", client_lan_ip); + + if(client_lan_ip == INVALID_IP_ADDR) + { + IPACMERR("Invalid ip address received\n"); + return -1; + } + + /* check for duplicate events */ + for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++) + { + if(PwrSaveIfs[cnt] == client_lan_ip) + { + IPACMDBG("The client 0x%x is already in power save\n", client_lan_ip); + return 0; + } + } + + for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++) + { + if(PwrSaveIfs[cnt] == 0) + { + PwrSaveIfs[cnt] = client_lan_ip; + break; + } + } + + for(cnt = 0; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip == client_lan_ip && + 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; + } + + cache[cnt].enabled = false; + cache[cnt].rule_hdl = 0; + } + } + + return 0; +} + +int NatApp::ResetPwrSaveIf(uint32_t client_lan_ip) +{ + int cnt; + ipa_nat_ipv4_rule nat_rule; + + IPACMDBG_H("Received ip address: 0x%x\n", client_lan_ip); + + if(client_lan_ip == INVALID_IP_ADDR) + { + IPACMERR("Invalid ip address received\n"); + return -1; + } + + for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++) + { + if(PwrSaveIfs[cnt] == client_lan_ip) + { + PwrSaveIfs[cnt] = 0; + break; + } + } + + for(cnt = 0; cnt < max_entries; cnt++) + { + IPACMDBG("cache (%d): enable %d, ip 0x%x\n", cnt, cache[cnt].enabled, cache[cnt].private_ip); + + if(cache[cnt].private_ip == client_lan_ip && + cache[cnt].enabled == false) + { + memset(&nat_rule, 0 , sizeof(nat_rule)); + nat_rule.private_ip = cache[cnt].private_ip; + nat_rule.target_ip = cache[cnt].target_ip; + nat_rule.target_port = cache[cnt].target_port; + nat_rule.private_port = cache[cnt].private_port; + nat_rule.public_port = cache[cnt].public_port; + nat_rule.protocol = cache[cnt].protocol; + + if(ipa_nat_add_ipv4_rule(nat_table_hdl, &nat_rule, &cache[cnt].rule_hdl) < 0) + { + IPACMERR("unable to add the rule delete from cache\n"); + memset(&cache[cnt], 0, sizeof(cache[cnt])); + curCnt--; + continue; + } + cache[cnt].enabled = true; + + IPACMDBG("On power reset added below rule successfully\n"); + iptodot("Private IP", nat_rule.private_ip); + iptodot("Target IP", nat_rule.target_ip); + IPACMDBG("Private Port:%d \t Target Port: %d\t", nat_rule.private_port, nat_rule.target_port); + IPACMDBG("Public Port:%d\n", nat_rule.public_port); + IPACMDBG("protocol: %d\n", nat_rule.protocol); + + } + } + + return -1; +} + +uint32_t NatApp::GetTableHdl(uint32_t in_ip_addr) +{ + if(in_ip_addr == pub_ip_addr) + { + return nat_table_hdl; + } + + return -1; +} + +void NatApp::AddTempEntry(const nat_table_entry *new_entry) +{ + int cnt; + + IPACMDBG("Received below Temp Nat entry\n"); + iptodot("Private IP", new_entry->private_ip); + iptodot("Target IP", new_entry->target_ip); + IPACMDBG("Private Port: %d\t Target Port: %d\t", new_entry->private_port, new_entry->target_port); + IPACMDBG("protocolcol: %d\n", new_entry->protocol); + + if(isAlgPort(new_entry->protocol, new_entry->private_port) || + isAlgPort(new_entry->protocol, new_entry->target_port)) + { + IPACMDBG("connection using ALG Port. Dont insert into nat cache\n"); + return; + } + + if(ChkForDup(new_entry)) + { + return; + } + + for(cnt=0; cnt<MAX_TEMP_ENTRIES; cnt++) + { + if(temp[cnt].private_ip == new_entry->private_ip && + temp[cnt].target_ip == new_entry->target_ip && + temp[cnt].private_port == new_entry->private_port && + temp[cnt].target_port == new_entry->target_port && + temp[cnt].protocol == new_entry->protocol) + { + IPACMDBG("Received duplicate Temp entry\n"); + return; + } + } + + for(cnt=0; cnt<MAX_TEMP_ENTRIES; cnt++) + { + if(temp[cnt].private_ip == 0 && + temp[cnt].target_ip == 0) + { + memcpy(&temp[cnt], new_entry, sizeof(nat_table_entry)); + IPACMDBG("Added Temp Entry\n"); + return; + } + } + + IPACMDBG("Unable to add temp entry, cache full\n"); + return; +} + +void NatApp::DeleteTempEntry(const nat_table_entry *entry) +{ + int cnt; + + IPACMDBG("Received below nat entry\n"); + iptodot("Private IP", entry->private_ip); + iptodot("Target IP", entry->target_ip); + IPACMDBG("Private Port: %d\t Target Port: %d\n", entry->private_port, entry->target_port); + IPACMDBG("protocol: %d\n", entry->protocol); + + for(cnt=0; cnt<MAX_TEMP_ENTRIES; cnt++) + { + if(temp[cnt].private_ip == entry->private_ip && + temp[cnt].target_ip == entry->target_ip && + temp[cnt].private_port == entry->private_port && + temp[cnt].target_port == entry->target_port && + temp[cnt].protocol == entry->protocol) + { + memset(&temp[cnt], 0, sizeof(nat_table_entry)); + IPACMDBG("Delete Temp Entry\n"); + return; + } + } + + IPACMDBG("No Such Temp Entry exists\n"); + return; +} + +void NatApp::FlushTempEntries(uint32_t ip_addr, bool isAdd, + bool isDummy) +{ + int cnt; + int ret; + + IPACMDBG_H("Received below with isAdd:%d ", isAdd); + iptodot("IP Address: ", ip_addr); + + for(cnt=0; cnt<MAX_TEMP_ENTRIES; cnt++) + { + if(temp[cnt].private_ip == ip_addr || + temp[cnt].target_ip == ip_addr) + { + if(isAdd) + { + if(temp[cnt].public_ip == pub_ip_addr) + { + if (isDummy) { + /* To avoild DL expections for non IPA path */ + temp[cnt].private_ip = temp[cnt].public_ip; + temp[cnt].private_port = temp[cnt].public_port; + IPACMDBG("Flushing dummy temp rule"); + iptodot("Private IP", temp[cnt].private_ip); + } + + ret = AddEntry(&temp[cnt]); + if(ret) + { + IPACMERR("unable to add temp entry: %d\n", ret); + continue; + } + } + } + memset(&temp[cnt], 0, sizeof(nat_table_entry)); + } + } + + return; +} + +int NatApp::DelEntriesOnClntDiscon(uint32_t ip_addr) +{ + int cnt, tmp = 0; + IPACMDBG_H("Received IP address: 0x%x\n", ip_addr); + + if(ip_addr == INVALID_IP_ADDR) + { + IPACMERR("Invalid ip address received\n"); + return -1; + } + + for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++) + { + if(PwrSaveIfs[cnt] == ip_addr) + { + PwrSaveIfs[cnt] = 0; + IPACMDBG("Remove %d power save entry\n", cnt); + break; + } + } + + for(cnt = 0; cnt < max_entries; cnt++) + { + if(cache[cnt].private_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; + } + else + { + IPACMDBG("won't delete the rule\n"); + cache[cnt].enabled = false; + tmp++; + } + } + IPACMDBG("won't delete the rule for entry %d, enabled %d\n",cnt, cache[cnt].enabled); + } + } + + IPACMDBG("Deleted (but cached) %d entries\n", tmp); + return 0; +} + +int NatApp::DelEntriesOnSTAClntDiscon(uint32_t ip_addr) +{ + int cnt, tmp = curCnt; + IPACMDBG_H("Received IP address: 0x%x\n", ip_addr); + + if(ip_addr == INVALID_IP_ADDR) + { + IPACMERR("Invalid ip address received\n"); + return -1; + } + + + 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; +} + +void NatApp::CacheEntry(const nat_table_entry *rule) +{ + int cnt; + + if(rule->private_ip == 0 || + rule->target_ip == 0 || + rule->private_port == 0 || + rule->target_port == 0 || + rule->protocol == 0) + { + IPACMERR("Invalid Connection, ignoring it\n"); + return; + } + + if(!ChkForDup(rule)) + { + for(cnt=0; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip == 0 && + cache[cnt].target_ip == 0 && + cache[cnt].private_port == 0 && + cache[cnt].target_port == 0 && + cache[cnt].protocol == 0) + { + break; + } + } + + if(max_entries == cnt) + { + IPACMERR("Error: Unable to add, reached maximum rules\n"); + return; + } + else + { + cache[cnt].enabled = false; + cache[cnt].rule_hdl = 0; + cache[cnt].private_ip = rule->private_ip; + cache[cnt].target_ip = rule->target_ip; + cache[cnt].target_port = rule->target_port; + cache[cnt].private_port = rule->private_port; + cache[cnt].protocol = rule->protocol; + cache[cnt].timestamp = 0; + cache[cnt].public_port = rule->public_port; + cache[cnt].public_ip = rule->public_ip; + cache[cnt].dst_nat = rule->dst_nat; + curCnt++; + } + + } + else + { + IPACMERR("Duplicate rule. Ignore it\n"); + return; + } + + IPACMDBG("Cached rule(%d) successfully\n", cnt); + return; +} + +void NatApp::Read_TcpUdp_Timeout(void) { +#ifdef FEATURE_IPACM_HAL + tcp_timeout = 432000; + udp_timeout = 180; + IPACMDBG_H("udp timeout value: %d\n", udp_timeout); + IPACMDBG_H("tcp timeout value: %d\n", tcp_timeout); +#else + FILE *udp_fd = NULL, *tcp_fd = NULL; + /* Read UDP timeout value */ + udp_fd = fopen(IPACM_UDP_FULL_FILE_NAME, "r"); + if (udp_fd == NULL) { + IPACMERR("unable to open %s\n", IPACM_UDP_FULL_FILE_NAME); + goto fail; + } + + if (fscanf(udp_fd, "%d", &udp_timeout) != 1) { + IPACMERR("Error reading udp timeout\n"); + } + IPACMDBG_H("udp timeout value: %d\n", udp_timeout); + + + /* Read TCP timeout value */ + tcp_fd = fopen(IPACM_TCP_FULL_FILE_NAME, "r"); + if (tcp_fd == NULL) { + IPACMERR("unable to open %s\n", IPACM_TCP_FULL_FILE_NAME); + goto fail; + } + + + if (fscanf(tcp_fd, "%d", &tcp_timeout) != 1) { + IPACMERR("Error reading tcp timeout\n"); + } + IPACMDBG_H("tcp timeout value: %d\n", tcp_timeout); + +fail: + if (udp_fd) { + fclose(udp_fd); + } + if (tcp_fd) { + fclose(tcp_fd); + } +#endif + return; +} |