summaryrefslogtreecommitdiff
path: root/ipacm/src/IPACM_ConntrackListener.cpp
diff options
context:
space:
mode:
authorSkylar Chang <chiaweic@codeaurora.org>2016-02-08 12:07:25 -0800
committerSkylar Chang <chiaweic@codeaurora.org>2016-04-11 14:51:41 -0700
commit1254fa127b4abc7747d02d52ba2bb8536ac81574 (patch)
tree4ae7911a836f5cb080d0af014394df5ca2f97f42 /ipacm/src/IPACM_ConntrackListener.cpp
parent48c4dd4c5a52dd6c0c92e3102a30ba0f5bc0588a (diff)
downloadipacfg-mgr-1254fa127b4abc7747d02d52ba2bb8536ac81574.tar.gz
IPACM: Add support for non IPA data path
Add dummy nat rules to avoid exception for DL packets that takes non IPA HW data path. Change-Id: I008f90a9fea9e9bcff3f4adcdc499c7f897af963 Acked-by: Sunil Paidimarri <hisunil@qti.qualcomm.com> CRs-Fixed: 946920
Diffstat (limited to 'ipacm/src/IPACM_ConntrackListener.cpp')
-rw-r--r--ipacm/src/IPACM_ConntrackListener.cpp829
1 files changed, 481 insertions, 348 deletions
diff --git a/ipacm/src/IPACM_ConntrackListener.cpp b/ipacm/src/IPACM_ConntrackListener.cpp
index ab25bde..33023cb 100644
--- a/ipacm/src/IPACM_ConntrackListener.cpp
+++ b/ipacm/src/IPACM_ConntrackListener.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+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
@@ -46,7 +46,7 @@ IPACM_ConntrackListener::IPACM_ConntrackListener()
NatIfaceCnt = 0;
StaClntCnt = 0;
pNatIfaces = NULL;
- pConfig = NULL;
+ pConfig = IPACM_Config::GetInstance();;
memset(nat_iface_ipv4_addr, 0, sizeof(nat_iface_ipv4_addr));
memset(nonnat_iface_ipv4_addr, 0, sizeof(nonnat_iface_ipv4_addr));
@@ -58,6 +58,8 @@ IPACM_ConntrackListener::IPACM_ConntrackListener()
IPACM_EvtDispatcher::registr(IPA_PROCESS_CT_MESSAGE_V6, this);
IPACM_EvtDispatcher::registr(IPA_HANDLE_WLAN_UP, this);
IPACM_EvtDispatcher::registr(IPA_HANDLE_LAN_UP, this);
+ IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, this);
+ IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, this);
#ifdef CT_OPT
p_lan2lan = IPACM_LanToLan::getLan2LanInstance();
@@ -65,7 +67,7 @@ IPACM_ConntrackListener::IPACM_ConntrackListener()
}
void IPACM_ConntrackListener::event_callback(ipa_cm_event_id evt,
- void *data)
+ void *data)
{
ipacm_event_iface_up *wan_down = NULL;
@@ -119,168 +121,232 @@ void IPACM_ConntrackListener::event_callback(ipa_cm_event_id evt,
IPACM_ConntrackClient::UpdateTCPFilters(data, false);
break;
+ case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT:
+ IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT event\n");
+ HandleNonNatIPAddr(data, true);
+ break;
+
+ case IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT:
+ IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT event\n");
+ HandleNonNatIPAddr(data, false);
+ break;
+
default:
IPACMDBG("Ignore cmd %d\n", evt);
break;
}
}
-void IPACM_ConntrackListener::HandleNeighIpAddrAddEvt(ipacm_event_data_all *data)
+
+int IPACM_ConntrackListener::CheckNatIface(
+ ipacm_event_data_all *data, bool *NatIface)
{
int fd = 0, len = 0, cnt, i, j;
struct ifreq ifr;
- bool isNatIface = false;
+ *NatIface = false;
- if(data->ipv4_addr == 0 || data->iptype != IPA_IP_v4)
+ if (data->ipv4_addr == 0 || data->iptype != IPA_IP_v4)
{
- IPACMDBG("Ignoring IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT EVENT\n");
- return;
+ IPACMDBG("Ignoring\n");
+ return IPACM_FAILURE;
}
- IPACMDBG("\n");
IPACMDBG("Received interface index %d with ip type: %d", data->if_index, data->iptype);
iptodot(" and ipv4 address", data->ipv4_addr);
- if(pConfig == NULL)
+ if (pConfig == NULL)
{
pConfig = IPACM_Config::GetInstance();
- if(pConfig == NULL)
+ if (pConfig == NULL)
{
IPACMERR("Unable to get Config instance\n");
- return;
+ return IPACM_FAILURE;
}
}
-
cnt = pConfig->GetNatIfacesCnt();
NatIfaceCnt = cnt;
- if (pNatIfaces != NULL) {
+ IPACMDBG("Total Nat ifaces: %d\n", NatIfaceCnt);
+ if (pNatIfaces != NULL)
+ {
free(pNatIfaces);
pNatIfaces = NULL;
}
len = (sizeof(NatIfaces) * NatIfaceCnt);
pNatIfaces = (NatIfaces *)malloc(len);
- if (pNatIfaces == NULL) {
+ if (pNatIfaces == NULL)
+ {
IPACMERR("Unable to allocate memory for non nat ifaces\n");
- return;
+ return IPACM_FAILURE;
}
- memset(pNatIfaces, 0, len);
- if (pConfig->GetNatIfaces(NatIfaceCnt, pNatIfaces) != 0) {
+ memset(pNatIfaces, 0, len);
+ if (pConfig->GetNatIfaces(NatIfaceCnt, pNatIfaces) != 0)
+ {
IPACMERR("Unable to retrieve non nat ifaces\n");
- return;
+ return IPACM_FAILURE;
}
- IPACMDBG("Update %d Nat ifaces\n", NatIfaceCnt);
-
/* Search/Configure linux interface-index and map it to IPA interface-index */
- if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
PERROR("get interface name socket create failed");
- return;
+ return IPACM_FAILURE;
}
memset(&ifr, 0, sizeof(struct ifreq));
ifr.ifr_ifindex = data->if_index;
-
- if(ioctl(fd, SIOCGIFNAME, &ifr) < 0)
+ if (ioctl(fd, SIOCGIFNAME, &ifr) < 0)
{
PERROR("call_ioctl_on_dev: ioctl failed:");
close(fd);
- return;
+ return IPACM_FAILURE;
}
close(fd);
- for(i = 0; i < NatIfaceCnt; i++)
+ for (i = 0; i < NatIfaceCnt; i++)
{
- if(strncmp(ifr.ifr_name,
- pNatIfaces[i].iface_name,
- sizeof(pNatIfaces[i].iface_name)) == 0)
+ if (strncmp(ifr.ifr_name,
+ pNatIfaces[i].iface_name,
+ sizeof(pNatIfaces[i].iface_name)) == 0)
{
/* copy the ipv4 address to filter out downlink connections
ignore downlink after listening connection event from
conntrack as it is not destinated to private ip address */
IPACMDBG("Interface (%s) is nat\n", ifr.ifr_name);
- for(j = 0; j < MAX_NAT_IFACES; j++)
+ for (j = 0; j < MAX_IFACE_ADDRESS; j++)
{
/* check if duplicate NAT ip */
- if(nat_iface_ipv4_addr[j] == data->ipv4_addr)
- break;
+ if (nat_iface_ipv4_addr[j] == data->ipv4_addr)
+ {
+ *NatIface = true;
+ return IPACM_SUCCESS;
+ }
- if(nat_iface_ipv4_addr[j] == 0)
+ if (nat_iface_ipv4_addr[j] == 0)
{
nat_iface_ipv4_addr[j] = data->ipv4_addr;
- nat_inst->ResetPwrSaveIf(data->ipv4_addr);
- nat_inst->FlushTempEntries(data->ipv4_addr, true);
- break;
+ IPACMDBG_H("Nating connections of Interface (%s), entry (%d) ",
+ pNatIfaces[i].iface_name, j);
+ iptodot("with ipv4 address: ", nat_iface_ipv4_addr[j]);
+
+ *NatIface = true;
+ return IPACM_SUCCESS;
}
}
+ }
+ }
+
+ return IPACM_SUCCESS;
+}
- if(j == MAX_NAT_IFACES)
+void IPACM_ConntrackListener::HandleNonNatIPAddr(
+ void *inParam, bool AddOp)
+{
+ ipacm_event_data_all *data = (ipacm_event_data_all *)inParam;
+ bool NatIface = false;
+ int cnt, ret;
+
+ /* Handle only non nat ifaces, NAT iface should be handle
+ separately to avoid race conditions between route/nat
+ rules add/delete operations */
+ if (AddOp)
+ {
+ ret = CheckNatIface(data, &NatIface);
+ if (!NatIface && ret == IPACM_SUCCESS)
+ {
+ /* Cache the non nat iface ip address */
+ for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
{
- IPACMERR("Nat ifaces(%d) exceed maximum\n", j);
- break;
+ if (nonnat_iface_ipv4_addr[cnt] == 0)
+ {
+ nonnat_iface_ipv4_addr[cnt] = data->ipv4_addr;
+ /* Add dummy nat rule for non nat ifaces */
+ nat_inst->FlushTempEntries(data->ipv4_addr, true, true);
+ return;
+ }
}
-
-
- isNatIface = true;
- IPACMDBG_H("Nating connections of Interface (%s), entry (%d) ", pNatIfaces[i].iface_name, j);
- IPACMDBG_H(" with ipv4 address(0x%x): %d.%d.%d.%d\n", nat_iface_ipv4_addr[j],
- ((nat_iface_ipv4_addr[j]>>24) & 0xFF), ((nat_iface_ipv4_addr[j]>>16) & 0xFF),
- ((nat_iface_ipv4_addr[j]>>8) & 0xFF), (nat_iface_ipv4_addr[j] & 0xFF));
- break;
}
}
-
- /* Cache the non nat iface ip address */
- if(isNatIface != true)
+ else
{
- for(i = 0; i < MAX_NAT_IFACES; i++)
+ /* for delete operation */
+ for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
{
- if(nonnat_iface_ipv4_addr[i] == 0)
+ if (nonnat_iface_ipv4_addr[cnt] == data->ipv4_addr)
{
- nonnat_iface_ipv4_addr[i] = data->ipv4_addr;
+ IPACMDBG("Reseting ct filters, entry (%d) ", cnt);
+ iptodot("with ipv4 address", nonnat_iface_ipv4_addr[cnt]);
+ nonnat_iface_ipv4_addr[cnt] = 0;
nat_inst->FlushTempEntries(data->ipv4_addr, false);
- break;
+ nat_inst->DelEntriesOnClntDiscon(data->ipv4_addr);
+ return;
}
}
+
}
+ return;
}
-void IPACM_ConntrackListener::HandleNeighIpAddrDelEvt(uint32_t ipv4_addr)
+void IPACM_ConntrackListener::HandleNeighIpAddrAddEvt(
+ ipacm_event_data_all *data)
+{
+ bool NatIface = false;
+ int j, ret;
+
+ ret = CheckNatIface(data, &NatIface);
+ if (NatIface && ret == IPACM_SUCCESS)
+ {
+ for (j = 0; j < MAX_IFACE_ADDRESS; j++)
+ {
+ /* check if duplicate NAT ip */
+ if (nat_iface_ipv4_addr[j] == data->ipv4_addr)
+ break;
+
+ /* Cache the new nat iface address */
+ if (nat_iface_ipv4_addr[j] == 0)
+ {
+ nat_iface_ipv4_addr[j] = data->ipv4_addr;
+ iptodot("Nating connections of addr: ", nat_iface_ipv4_addr[j]);
+ break;
+ }
+ }
+
+ /* Add the cached temp entries to NAT table */
+ if (j != MAX_IFACE_ADDRESS)
+ {
+ nat_inst->ResetPwrSaveIf(data->ipv4_addr);
+ nat_inst->FlushTempEntries(data->ipv4_addr, true);
+ }
+ }
+ return;
+}
+
+void IPACM_ConntrackListener::HandleNeighIpAddrDelEvt(
+ uint32_t ipv4_addr)
{
int cnt;
if(ipv4_addr == 0)
{
- IPACMDBG("Ignoring IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT EVENT\n");
+ IPACMDBG("Ignoring\n");
return;
}
- IPACMDBG("\n");
- iptodot("Received ip addr", ipv4_addr);
- IPACMDBG("Entering NAT entry deletion checking\n");
-
- for(cnt = 0; cnt<MAX_NAT_IFACES; cnt++)
+ iptodot("HandleNeighIpAddrDelEvt(): Received ip addr", ipv4_addr);
+ for(cnt = 0; cnt<MAX_IFACE_ADDRESS; cnt++)
{
- if(nat_iface_ipv4_addr[cnt] == ipv4_addr)
+ if (nat_iface_ipv4_addr[cnt] == ipv4_addr)
{
IPACMDBG("Reseting ct nat iface, entry (%d) ", cnt);
iptodot("with ipv4 address", nat_iface_ipv4_addr[cnt]);
nat_iface_ipv4_addr[cnt] = 0;
- }
-
- if(nonnat_iface_ipv4_addr[cnt] == ipv4_addr)
- {
- IPACMDBG("Reseting ct filters, entry (%d) ", cnt);
- iptodot("with ipv4 address", nonnat_iface_ipv4_addr[cnt]);
- nonnat_iface_ipv4_addr[cnt] = 0;
+ nat_inst->FlushTempEntries(ipv4_addr, false);
+ nat_inst->DelEntriesOnClntDiscon(ipv4_addr);
}
}
- nat_inst->FlushTempEntries(ipv4_addr, false);
- nat_inst->DelEntriesOnClntDiscon(ipv4_addr);
return;
}
@@ -467,7 +533,7 @@ void ParseCTMessage(struct nf_conntrack *ct)
void ParseCTV6Message(struct nf_conntrack *ct)
{
- uint32_t status, timeout, secmark;
+ uint32_t status, timeout;
struct nfct_attr_grp_ipv6 orig_params;
uint8_t l4proto, tcp_flags, tcp_state;
@@ -628,6 +694,320 @@ void IPACM_ConntrackListener::ProcessCTMessage(void *param)
return;
}
+bool IPACM_ConntrackListener::AddIface(
+ nat_table_entry *rule, bool *isTempEntry)
+{
+ int cnt;
+
+ *isTempEntry = false;
+ /* check whether nat iface or not */
+ for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
+ {
+ if (nat_iface_ipv4_addr[cnt] != 0)
+ {
+ if (rule->private_ip == nat_iface_ipv4_addr[cnt] ||
+ rule->target_ip == nat_iface_ipv4_addr[cnt])
+ {
+ IPACMDBG("matched nat_iface_ipv4_addr entry(%d)\n", cnt);
+ iptodot("AddIface(): Nat entry match with ip addr",
+ nat_iface_ipv4_addr[cnt]);
+ return true;
+ }
+ }
+ }
+
+ /* check whether non nat iface or not, on Nat iface
+ add dummy rule by copying public ip to private ip */
+ for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
+ {
+ if (nonnat_iface_ipv4_addr[cnt] != 0)
+ {
+ if (rule->private_ip == nonnat_iface_ipv4_addr[cnt] ||
+ rule->target_ip == nonnat_iface_ipv4_addr[cnt])
+ {
+ IPACMDBG("matched non_nat_iface_ipv4_addr entry(%d)\n", cnt);
+ iptodot("AddIface(): Non Nat entry match with ip addr",
+ nat_iface_ipv4_addr[cnt]);
+
+ rule->private_ip = rule->public_ip;
+ rule->private_port = rule->public_port;
+ return true;
+ }
+ }
+ }
+
+ IPACMDBG_H("Not mtaching with non-nat ifaces\n");
+ if(pConfig == NULL)
+ {
+ pConfig = IPACM_Config::GetInstance();
+ if(pConfig == NULL)
+ {
+ IPACMERR("Unable to get Config instance\n");
+ return false;
+ }
+ }
+
+ if (pConfig->isPrivateSubnet(rule->private_ip) ||
+ pConfig->isPrivateSubnet(rule->target_ip))
+ {
+ IPACMDBG("Matching with Private subnet\n");
+ *isTempEntry = true;
+ return true;
+ }
+
+ return false;
+}
+
+void IPACM_ConntrackListener::AddORDeleteNatEntry(const nat_entry_bundle *input)
+{
+ u_int8_t tcp_state;
+
+ if (nat_inst == NULL)
+ {
+ IPACMERR("Nat instance is NULL, unable to add or delete\n");
+ return;
+ }
+
+ IPACMDBG_H("Below Nat Entry will either be added or deleted\n");
+ iptodot("AddORDeleteNatEntry(): target ip or dst ip",
+ input->rule->target_ip);
+ IPACMDBG("target port or dst port: 0x%x Decimal:%d\n",
+ input->rule->target_port, input->rule->target_port);
+ iptodot("AddORDeleteNatEntry(): private ip or src ip",
+ input->rule->private_ip);
+ IPACMDBG("private port or src port: 0x%x, Decimal:%d\n",
+ input->rule->private_port, input->rule->private_port);
+ IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n",
+ input->rule->public_port, input->rule->public_port);
+ IPACMDBG("Protocol: %d, destination nat flag: %d\n",
+ input->rule->protocol, input->rule->dst_nat);
+
+ if (IPPROTO_TCP == input->rule->protocol)
+ {
+ tcp_state = nfct_get_attr_u8(input->ct, ATTR_TCP_STATE);
+ if (TCP_CONNTRACK_ESTABLISHED == tcp_state)
+ {
+ IPACMDBG("TCP state TCP_CONNTRACK_ESTABLISHED(%d)\n", tcp_state);
+ if (!CtList->isWanUp())
+ {
+ IPACMDBG("Wan is not up, cache connections\n");
+ nat_inst->CacheEntry(input->rule);
+ }
+ else if (input->isTempEntry)
+ {
+ nat_inst->AddTempEntry(input->rule);
+ }
+ else
+ {
+ nat_inst->AddEntry(input->rule);
+ }
+ }
+ else if (TCP_CONNTRACK_FIN_WAIT == tcp_state ||
+ input->type == NFCT_T_DESTROY)
+ {
+ IPACMDBG("TCP state TCP_CONNTRACK_FIN_WAIT(%d) "
+ "or type NFCT_T_DESTROY(%d)\n", tcp_state, input->type);
+
+ nat_inst->DeleteEntry(input->rule);
+ nat_inst->DeleteTempEntry(input->rule);
+ }
+ else
+ {
+ IPACMDBG("Ignore tcp state: %d and type: %d\n",
+ tcp_state, input->type);
+ }
+
+ }
+ else if (IPPROTO_UDP == input->rule->protocol)
+ {
+ if (NFCT_T_NEW == input->type)
+ {
+ IPACMDBG("New UDP connection at time %ld\n", time(NULL));
+ if (!CtList->isWanUp())
+ {
+ IPACMDBG("Wan is not up, cache connections\n");
+ nat_inst->CacheEntry(input->rule);
+ }
+ else if (input->isTempEntry)
+ {
+ nat_inst->AddTempEntry(input->rule);
+ }
+ else
+ {
+ nat_inst->AddEntry(input->rule);
+ }
+ }
+ else if (NFCT_T_DESTROY == input->type)
+ {
+ IPACMDBG("UDP connection close at time %ld\n", time(NULL));
+ nat_inst->DeleteEntry(input->rule);
+ nat_inst->DeleteTempEntry(input->rule);
+ }
+ }
+
+ return;
+}
+
+void IPACM_ConntrackListener::PopulateTCPorUDPEntry(
+ struct nf_conntrack *ct,
+ uint32_t status,
+ nat_table_entry *rule)
+{
+ if (IPS_DST_NAT == status)
+ {
+ IPACMDBG("Destination NAT\n");
+ rule->dst_nat = true;
+
+ IPACMDBG("Parse reply tuple\n");
+ rule->target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
+ rule->target_ip = ntohl(rule->target_ip);
+ iptodot("PopulateTCPorUDPEntry(): target ip", rule->target_ip);
+
+ /* Retriev target/dst port */
+ rule->target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
+ rule->target_port = ntohs(rule->target_port);
+ if (0 == rule->target_port)
+ {
+ IPACMDBG("unable to retrieve target port\n");
+ }
+
+ rule->public_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
+ rule->public_port = ntohs(rule->public_port);
+
+ /* Retriev src/private ip address */
+ rule->private_ip = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC);
+ rule->private_ip = ntohl(rule->private_ip);
+ iptodot("PopulateTCPorUDPEntry(): private ip", rule->private_ip);
+ if (0 == rule->private_ip)
+ {
+ IPACMDBG("unable to retrieve private ip address\n");
+ }
+
+ /* Retriev src/private port */
+ rule->private_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC);
+ rule->private_port = ntohs(rule->private_port);
+ if (0 == rule->private_port)
+ {
+ IPACMDBG("unable to retrieve private port\n");
+ }
+ }
+ else if (IPS_SRC_NAT == status)
+ {
+ IPACMDBG("Source NAT\n");
+ rule->dst_nat = false;
+
+ /* Retriev target/dst ip address */
+ IPACMDBG("Parse source tuple\n");
+ rule->target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST);
+ rule->target_ip = ntohl(rule->target_ip);
+ iptodot("PopulateTCPorUDPEntry(): target ip", rule->target_ip);
+ if (0 == rule->target_ip)
+ {
+ IPACMDBG("unable to retrieve target ip address\n");
+ }
+ /* Retriev target/dst port */
+ rule->target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
+ rule->target_port = ntohs(rule->target_port);
+ if (0 == rule->target_port)
+ {
+ IPACMDBG("unable to retrieve target port\n");
+ }
+
+ /* Retriev public port */
+ rule->public_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST);
+ rule->public_port = ntohs(rule->public_port);
+ if (0 == rule->public_port)
+ {
+ IPACMDBG("unable to retrieve public port\n");
+ }
+
+ /* Retriev src/private ip address */
+ rule->private_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
+ rule->private_ip = ntohl(rule->private_ip);
+ iptodot("PopulateTCPorUDPEntry(): private ip", rule->private_ip);
+ if (0 == rule->private_ip)
+ {
+ IPACMDBG("unable to retrieve private ip address\n");
+ }
+
+ /* Retriev src/private port */
+ rule->private_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
+ rule->private_port = ntohs(rule->private_port);
+ if (0 == rule->private_port)
+ {
+ IPACMDBG("unable to retrieve private port\n");
+ }
+ }
+
+ return;
+}
+
+#ifdef CT_OPT
+void IPACM_ConntrackListener::HandleLan2Lan(struct nf_conntrack *ct,
+ enum nf_conntrack_msg_type type,
+ nat_table_entry *rule)
+{
+ ipacm_event_connection lan2lan_conn = { 0 };
+
+ if (p_lan2lan == NULL)
+ {
+ IPACMERR("Lan2Lan Instance is null\n");
+ return;
+ }
+
+ lan2lan_conn.iptype = IPA_IP_v4;
+ lan2lan_conn.src_ipv4_addr = orig_src_ip;
+ lan2lan_conn.dst_ipv4_addr = orig_dst_ip;
+
+ if (((IPPROTO_UDP == rule->protocol) && (NFCT_T_NEW == type)) ||
+ ((IPPROTO_TCP == rule->protocol) && (nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_ESTABLISHED)))
+ {
+ p_lan2lan->handle_new_connection(&lan2lan_conn);
+ }
+ else if ((IPPROTO_UDP == rule->protocol && NFCT_T_DESTROY == type) ||
+ (IPPROTO_TCP == rule->protocol &&
+ nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_FIN_WAIT))
+ {
+ p_lan2lan->handle_del_connection(&lan2lan_conn);
+ }
+}
+#endif
+
+void IPACM_ConntrackListener::CheckSTAClient(
+ const nat_table_entry *rule, bool *isTempEntry)
+{
+ int nCnt;
+
+ /* Check whether target is in STA client list or not
+ if not ignore the connection */
+ if(!isStaMode || (StaClntCnt == 0))
+ {
+ return;
+ }
+
+ if((sta_clnt_ipv4_addr[0] & STA_CLNT_SUBNET_MASK) !=
+ (rule->target_ip & STA_CLNT_SUBNET_MASK))
+ {
+ IPACMDBG("STA client subnet mask not matching\n");
+ return;
+ }
+
+ 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);
+ return;
+ }
+ }
+
+ IPACMDBG_H("Not matching with STA Clnt Ip Addrs 0x%x\n",
+ rule->target_ip);
+ *isTempEntry = true;
+}
/* conntrack send in host order and ipa expects in host order */
void IPACM_ConntrackListener::ProcessTCPorUDPMsg(
@@ -636,19 +1016,16 @@ void IPACM_ConntrackListener::ProcessTCPorUDPMsg(
u_int8_t l4proto)
{
nat_table_entry rule;
- u_int8_t tcp_state;
uint32_t status = 0;
- IPACM_Config *pConfig;
uint32_t orig_src_ip, orig_dst_ip;
- bool isTempEntry = false;
+ bool isAdd = false;
- memset(&rule, 0, sizeof(rule));
- pConfig = IPACM_Config::GetInstance();
- if(pConfig == NULL)
- {
- IPACMERR("Unable to get Config instance\n");
- }
+ nat_entry_bundle nat_entry;
+ nat_entry.isTempEntry = false;
+ nat_entry.ct = ct;
+ nat_entry.type = type;
+ memset(&rule, 0, sizeof(rule));
IPACMDBG("Received type:%d with proto:%d\n", type, l4proto);
status = nfct_get_attr_u32(ct, ATTR_STATUS);
@@ -695,116 +1072,19 @@ void IPACM_ConntrackListener::ProcessTCPorUDPMsg(
else
{
IPACMDBG_H("Neither orig src ip:0x%x Nor orig Dst IP:0x%x equal to wan ip:0x%x\n",
- orig_src_ip, orig_dst_ip, wan_ipaddr);
+ orig_src_ip, orig_dst_ip, wan_ipaddr);
#ifdef CT_OPT
- if(p_lan2lan == NULL)
- {
- IPACMERR("Lan2Lan Instance is null\n");
- goto IGNORE;
- }
-
- ipacm_event_connection lan2lan_conn = { 0 };
- lan2lan_conn.iptype = IPA_IP_v4;
- lan2lan_conn.src_ipv4_addr = orig_src_ip;
- lan2lan_conn.dst_ipv4_addr = orig_dst_ip;
-
- if(((IPPROTO_UDP == rule.protocol) && (NFCT_T_NEW == type)) ||
- ((IPPROTO_TCP == rule.protocol) && (nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_ESTABLISHED)))
- {
- p_lan2lan->handle_new_connection(&lan2lan_conn);
- }
- else if((IPPROTO_UDP == rule.protocol && NFCT_T_DESTROY == type) ||
- (IPPROTO_TCP == rule.protocol &&
- nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_FIN_WAIT))
- {
- p_lan2lan->handle_del_connection(&lan2lan_conn);
- }
+ HandleLan2Lan(ct, type, &rule);
#endif
- return;
- }
+ return;
+ }
}
- if(IPS_DST_NAT == status)
+ if(IPS_DST_NAT == status || IPS_SRC_NAT == status)
{
- IPACMDBG("Destination NAT\n");
- rule.dst_nat = true;
-
- IPACMDBG("Parse reply tuple\n");
- rule.target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
- rule.target_ip = ntohl(rule.target_ip);
-
- /* Retriev target/dst port */
- rule.target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
- rule.target_port = ntohs(rule.target_port);
- if(0 == rule.target_port)
- {
- IPACMDBG("unable to retrieve target port\n");
- }
-
- rule.public_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
- rule.public_port = ntohs(rule.public_port);
-
- /* Retriev src/private ip address */
- rule.private_ip = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC);
- rule.private_ip = ntohl(rule.private_ip);
- if(0 == rule.private_ip)
- {
- IPACMDBG("unable to retrieve private ip address\n");
- }
-
- /* Retriev src/private port */
- rule.private_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC);
- rule.private_port = ntohs(rule.private_port);
- if(0 == rule.private_port)
- {
- IPACMDBG("unable to retrieve private port\n");
- }
- }
- else if(IPS_SRC_NAT == status)
- {
- IPACMDBG("Source NAT\n");
- rule.dst_nat = false;
-
- /* Retriev target/dst ip address */
- IPACMDBG("Parse source tuple\n");
- rule.target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST);
- rule.target_ip = ntohl(rule.target_ip);
- if(0 == rule.target_ip)
- {
- IPACMDBG("unable to retrieve target ip address\n");
- }
- /* Retriev target/dst port */
- rule.target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
- rule.target_port = ntohs(rule.target_port);
- if(0 == rule.target_port)
- {
- IPACMDBG("unable to retrieve target port\n");
- }
-
- /* Retriev public port */
- rule.public_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST);
- rule.public_port = ntohs(rule.public_port);
- if(0 == rule.public_port)
- {
- IPACMDBG("unable to retrieve public port\n");
- }
-
- /* Retriev src/private ip address */
- rule.private_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
- rule.private_ip = ntohl(rule.private_ip);
- if(0 == rule.private_ip)
- {
- IPACMDBG("unable to retrieve private ip address\n");
- }
-
- /* Retriev src/private port */
- rule.private_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
- rule.private_port = ntohs(rule.private_port);
- if(0 == rule.private_port)
- {
- IPACMDBG("unable to retrieve private port\n");
- }
+ PopulateTCPorUDPEntry(ct, status, &rule);
+ rule.public_ip = wan_ipaddr;
}
else
{
@@ -812,188 +1092,41 @@ void IPACM_ConntrackListener::ProcessTCPorUDPMsg(
goto IGNORE;
}
- if(rule.private_ip != wan_ipaddr)
+ if (rule.private_ip != wan_ipaddr)
{
- int cnt;
- for(cnt = 0; cnt < MAX_NAT_IFACES; cnt++)
+ isAdd = AddIface(&rule, &nat_entry.isTempEntry);
+ if (!isAdd)
{
- if(nat_iface_ipv4_addr[cnt] != 0)
- {
- if(rule.private_ip == nat_iface_ipv4_addr[cnt] ||
- rule.target_ip == nat_iface_ipv4_addr[cnt])
- {
- IPACMDBG("matched nat_iface_ipv4_addr entry(%d)\n", cnt);
- iptodot("ProcessTCPorUDPMsg(): Nat entry match with ip addr",
- nat_iface_ipv4_addr[cnt]);
- break;
- }
- }
- }
-
- if(cnt == MAX_NAT_IFACES)
- {
- IPACMDBG_H("Not mtaching with nat ifaces\n");
- if(pConfig == NULL)
- {
- goto IGNORE;
- }
-
- if(pConfig->isPrivateSubnet(rule.private_ip) ||
- pConfig->isPrivateSubnet(rule.target_ip))
- {
- IPACMDBG("Matching with Private subnet\n");
- isTempEntry = true;
- }
- else
- {
- goto IGNORE;
- }
+ goto IGNORE;
}
-
}
else
{
- if(isStaMode) {
+ if (isStaMode)
+ {
IPACMDBG("In STA mode, ignore connections destinated to STA interface\n");
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;
- }
-
- /* 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_H("Not matching with STA Clnt Ip Addrs 0x%x\n",
- rule.target_ip);
- isTempEntry = true;
-
-
-ADD:
- IPACMDBG_H("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);
- iptodot("private ip or src ip", rule.private_ip);
- IPACMDBG("private port or src port: 0x%x, Decimal:%d\n", rule.private_port, rule.private_port);
- IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n", rule.public_port, rule.public_port);
- IPACMDBG("Protocol: %d, destination nat flag: %d\n", rule.protocol, rule.dst_nat);
-
- rule.public_ip = wan_ipaddr;
- if(IPPROTO_TCP == rule.protocol)
- {
- if(nat_inst == NULL)
- {
- return;
- }
-
- tcp_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE);
- if(TCP_CONNTRACK_ESTABLISHED == tcp_state)
- {
- IPACMDBG("TCP state TCP_CONNTRACK_ESTABLISHED(%d)\n", tcp_state);
- if(!CtList->isWanUp())
- {
- IPACMDBG("Wan is not up, cache connections\n");
- nat_inst->CacheEntry(&rule);
- }
- else if(isTempEntry)
- {
- nat_inst->AddTempEntry(&rule);
- }
- else
- {
- nat_inst->AddEntry(&rule);
- }
- }
- else if(TCP_CONNTRACK_FIN_WAIT == tcp_state ||
- type == NFCT_T_DESTROY)
- {
- IPACMDBG("TCP state TCP_CONNTRACK_FIN_WAIT(%d) "
- "or type NFCT_T_DESTROY(%d)\n", tcp_state, type);
-
- nat_inst->DeleteEntry(&rule);
- nat_inst->DeleteTempEntry(&rule);
- }
- else
- {
- IPACMDBG("Ignore tcp state: %d and type: %d\n", tcp_state, type);
- }
-
- }
- else if(IPPROTO_UDP == rule.protocol)
- {
- if(nat_inst == NULL)
- {
- return;
- }
-
- if(NFCT_T_NEW == type)
- {
- IPACMDBG("New UDP connection at time %ld\n", time(NULL));
- if(!CtList->isWanUp())
- {
- IPACMDBG("Wan is not up, cache connections\n");
- nat_inst->CacheEntry(&rule);
- }
- else if(isTempEntry)
- {
- nat_inst->AddTempEntry(&rule);
- }
- else
- {
- nat_inst->AddEntry(&rule);
- }
- }
- else if(NFCT_T_DESTROY == type)
- {
- IPACMDBG("UDP connection close at time %ld\n", time(NULL));
- nat_inst->DeleteEntry(&rule);
- nat_inst->DeleteTempEntry(&rule);
- }
- }
- else
- {
- IPACMDBG("Ignore protocol: %d and type: %d\n", rule.protocol, type);
+ 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;
}
+ CheckSTAClient(&rule, &nat_entry.isTempEntry);
+ nat_entry.rule = &rule;
+ AddORDeleteNatEntry(&nat_entry);
return;
IGNORE:
IPACMDBG_H("ignoring below Nat Entry\n");
- iptodot("target ip or dst ip", rule.target_ip);
+ iptodot("ProcessTCPorUDPMsg(): 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);
- iptodot("private ip or src ip", rule.private_ip);
+ iptodot("ProcessTCPorUDPMsg(): private ip or src ip", rule.private_ip);
IPACMDBG("private port or src port: 0x%x, Decimal:%d\n", rule.private_port, rule.private_port);
IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n", rule.public_port, rule.public_port);
IPACMDBG("Protocol: %d, destination nat flag: %d\n", rule.protocol, rule.dst_nat);
-
return;
}