Home | History | Annotate | Download | only in src
      1 /*
      2 Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
      3 
      4 Redistribution and use in source and binary forms, with or without
      5 modification, are permitted provided that the following conditions are
      6 met:
      7 		* Redistributions of source code must retain the above copyright
      8 			notice, this list of conditions and the following disclaimer.
      9 		* Redistributions in binary form must reproduce the above
     10 			copyright notice, this list of conditions and the following
     11 			disclaimer in the documentation and/or other materials provided
     12 			with the distribution.
     13 		* Neither the name of The Linux Foundation nor the names of its
     14 			contributors may be used to endorse or promote products derived
     15 			from this software without specific prior written permission.
     16 
     17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 */
     29 
     30 #include <sys/ioctl.h>
     31 #include <net/if.h>
     32 
     33 #include "IPACM_ConntrackListener.h"
     34 #include "IPACM_ConntrackClient.h"
     35 #include "IPACM_EvtDispatcher.h"
     36 #include "IPACM_Iface.h"
     37 #include "IPACM_Wan.h"
     38 
     39 IPACM_ConntrackListener::IPACM_ConntrackListener()
     40 {
     41 	 IPACMDBG("\n");
     42 
     43 	 isNatThreadStart = false;
     44 	 isCTReg = false;
     45 	 WanUp = false;
     46 	 nat_inst = NatApp::GetInstance();
     47 
     48 	 NatIfaceCnt = 0;
     49 	 StaClntCnt = 0;
     50 	 pNatIfaces = NULL;
     51 	 pConfig = IPACM_Config::GetInstance();;
     52 
     53 	 memset(nat_iface_ipv4_addr, 0, sizeof(nat_iface_ipv4_addr));
     54 	 memset(nonnat_iface_ipv4_addr, 0, sizeof(nonnat_iface_ipv4_addr));
     55 	 memset(sta_clnt_ipv4_addr, 0, sizeof(sta_clnt_ipv4_addr));
     56 
     57 	 IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, this);
     58 	 IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, this);
     59 	 IPACM_EvtDispatcher::registr(IPA_PROCESS_CT_MESSAGE, this);
     60 	 IPACM_EvtDispatcher::registr(IPA_PROCESS_CT_MESSAGE_V6, this);
     61 	 IPACM_EvtDispatcher::registr(IPA_HANDLE_WLAN_UP, this);
     62 	 IPACM_EvtDispatcher::registr(IPA_HANDLE_LAN_UP, this);
     63 	 IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, this);
     64 	 IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, this);
     65 
     66 #ifdef CT_OPT
     67 	 p_lan2lan = IPACM_LanToLan::getLan2LanInstance();
     68 #endif
     69 }
     70 
     71 void IPACM_ConntrackListener::event_callback(ipa_cm_event_id evt,
     72 						void *data)
     73 {
     74 	 ipacm_event_iface_up *wan_down = NULL;
     75 
     76 	 if(data == NULL)
     77 	 {
     78 		 IPACMERR("Invalid Data\n");
     79 		 return;
     80 	 }
     81 
     82 	 switch(evt)
     83 	 {
     84 	 case IPA_PROCESS_CT_MESSAGE:
     85 			IPACMDBG("Received IPA_PROCESS_CT_MESSAGE event\n");
     86 			ProcessCTMessage(data);
     87 			break;
     88 
     89 #ifdef CT_OPT
     90 	 case IPA_PROCESS_CT_MESSAGE_V6:
     91 			IPACMDBG("Received IPA_PROCESS_CT_MESSAGE_V6 event\n");
     92 			ProcessCTV6Message(data);
     93 			break;
     94 #endif
     95 
     96 	 case IPA_HANDLE_WAN_UP:
     97 			IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n");
     98 			CreateConnTrackThreads();
     99 			TriggerWANUp(data);
    100 			break;
    101 
    102 	 case IPA_HANDLE_WAN_DOWN:
    103 			IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN event\n");
    104 			wan_down = (ipacm_event_iface_up *)data;
    105 			if(isWanUp())
    106 			{
    107 				TriggerWANDown(wan_down->ipv4_addr);
    108 			}
    109 			break;
    110 
    111 	/* if wlan or lan comes up after wan interface, modify
    112 		 tcp/udp filters to ignore local wlan or lan connections */
    113 	 case IPA_HANDLE_WLAN_UP:
    114 	 case IPA_HANDLE_LAN_UP:
    115 			IPACMDBG_H("Received event: %d with ifname: %s and address: 0x%x\n",
    116 							 evt, ((ipacm_event_iface_up *)data)->ifname,
    117 							 ((ipacm_event_iface_up *)data)->ipv4_addr);
    118 			if(isWanUp())
    119 			{
    120 				CreateConnTrackThreads();
    121 				IPACM_ConntrackClient::UpdateUDPFilters(data, false);
    122 				IPACM_ConntrackClient::UpdateTCPFilters(data, false);
    123 			}
    124 			break;
    125 
    126 	 case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT:
    127 		 IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT event\n");
    128 		 HandleNonNatIPAddr(data, true);
    129 		 break;
    130 
    131 	 case IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT:
    132 		 IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT event\n");
    133 		 HandleNonNatIPAddr(data, false);
    134 		 break;
    135 
    136 	 default:
    137 			IPACMDBG("Ignore cmd %d\n", evt);
    138 			break;
    139 	 }
    140 }
    141 
    142 int IPACM_ConntrackListener::CheckNatIface(
    143    ipacm_event_data_all *data, bool *NatIface)
    144 {
    145 	int fd = 0, len = 0, cnt, i;
    146 	struct ifreq ifr;
    147 	*NatIface = false;
    148 
    149 	if (data->ipv4_addr == 0 || data->iptype != IPA_IP_v4)
    150 	{
    151 		IPACMDBG("Ignoring\n");
    152 		return IPACM_FAILURE;
    153 	}
    154 
    155 	IPACMDBG("Received interface index %d with ip type: %d", data->if_index, data->iptype);
    156 	iptodot(" and ipv4 address", data->ipv4_addr);
    157 
    158 	if (pConfig == NULL)
    159 	{
    160 		pConfig = IPACM_Config::GetInstance();
    161 		if (pConfig == NULL)
    162 		{
    163 			IPACMERR("Unable to get Config instance\n");
    164 			return IPACM_FAILURE;
    165 		}
    166 	}
    167 
    168 	cnt = pConfig->GetNatIfacesCnt();
    169 	NatIfaceCnt = cnt;
    170 	IPACMDBG("Total Nat ifaces: %d\n", NatIfaceCnt);
    171 	if (pNatIfaces != NULL)
    172 	{
    173 		free(pNatIfaces);
    174 		pNatIfaces = NULL;
    175 	}
    176 
    177 	len = (sizeof(NatIfaces) * NatIfaceCnt);
    178 	pNatIfaces = (NatIfaces *)malloc(len);
    179 	if (pNatIfaces == NULL)
    180 	{
    181 		IPACMERR("Unable to allocate memory for non nat ifaces\n");
    182 		return IPACM_FAILURE;
    183 	}
    184 
    185 	memset(pNatIfaces, 0, len);
    186 	if (pConfig->GetNatIfaces(NatIfaceCnt, pNatIfaces) != 0)
    187 	{
    188 		IPACMERR("Unable to retrieve non nat ifaces\n");
    189 		return IPACM_FAILURE;
    190 	}
    191 
    192 	/* Search/Configure linux interface-index and map it to IPA interface-index */
    193 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    194 	{
    195 		PERROR("get interface name socket create failed");
    196 		return IPACM_FAILURE;
    197 	}
    198 
    199 	memset(&ifr, 0, sizeof(struct ifreq));
    200 	ifr.ifr_ifindex = data->if_index;
    201 	if (ioctl(fd, SIOCGIFNAME, &ifr) < 0)
    202 	{
    203 		PERROR("call_ioctl_on_dev: ioctl failed:");
    204 		close(fd);
    205 		return IPACM_FAILURE;
    206 	}
    207 	close(fd);
    208 
    209 	for (i = 0; i < NatIfaceCnt; i++)
    210 	{
    211 		if (strncmp(ifr.ifr_name,
    212 					pNatIfaces[i].iface_name,
    213 					sizeof(pNatIfaces[i].iface_name)) == 0)
    214 		{
    215 			IPACMDBG_H("Nat iface (%s), entry (%d), dont cache",
    216 						pNatIfaces[i].iface_name, i);
    217 			iptodot("with ipv4 address: ", nat_iface_ipv4_addr[i]);
    218 			*NatIface = true;
    219 			return IPACM_SUCCESS;
    220 		}
    221 	}
    222 
    223 	return IPACM_SUCCESS;
    224 }
    225 
    226 void IPACM_ConntrackListener::HandleNonNatIPAddr(
    227    void *inParam, bool AddOp)
    228 {
    229 	ipacm_event_data_all *data = (ipacm_event_data_all *)inParam;
    230 	bool NatIface = false;
    231 	int cnt, ret;
    232 
    233 	if (isStaMode)
    234 	{
    235 		IPACMDBG("In STA mode, don't add dummy rules for non nat ifaces\n");
    236 		return;
    237 	}
    238 
    239 	/* Handle only non nat ifaces, NAT iface should be handle
    240 	   separately to avoid race conditions between route/nat
    241 	   rules add/delete operations */
    242 	if (AddOp)
    243 	{
    244 		ret = CheckNatIface(data, &NatIface);
    245 		if (!NatIface && ret == IPACM_SUCCESS)
    246 		{
    247 			/* Cache the non nat iface ip address */
    248 			for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
    249 			{
    250 				if (nonnat_iface_ipv4_addr[cnt] == 0)
    251 				{
    252 					nonnat_iface_ipv4_addr[cnt] = data->ipv4_addr;
    253 					IPACMDBG("Add ip addr to non nat list (%d) ", cnt);
    254 					iptodot("with ipv4 address", nonnat_iface_ipv4_addr[cnt]);
    255 
    256 					/* Add dummy nat rule for non nat ifaces */
    257 					nat_inst->FlushTempEntries(data->ipv4_addr, true, true);
    258 					return;
    259 				}
    260 			}
    261 		}
    262 	}
    263 	else
    264 	{
    265 		/* for delete operation */
    266 		for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
    267 		{
    268 			if (nonnat_iface_ipv4_addr[cnt] == data->ipv4_addr)
    269 			{
    270 				IPACMDBG("Reseting ct filters, entry (%d) ", cnt);
    271 				iptodot("with ipv4 address", nonnat_iface_ipv4_addr[cnt]);
    272 				nonnat_iface_ipv4_addr[cnt] = 0;
    273 				nat_inst->FlushTempEntries(data->ipv4_addr, false);
    274 				nat_inst->DelEntriesOnClntDiscon(data->ipv4_addr);
    275 				return;
    276 			}
    277 		}
    278 
    279 	}
    280 
    281 	return;
    282 }
    283 
    284 void IPACM_ConntrackListener::HandleNeighIpAddrAddEvt(
    285    ipacm_event_data_all *data)
    286 {
    287 	bool NatIface = false;
    288 	int j, ret;
    289 
    290 	ret = CheckNatIface(data, &NatIface);
    291 	if (NatIface && ret == IPACM_SUCCESS)
    292 	{
    293 		for (j = 0; j < MAX_IFACE_ADDRESS; j++)
    294 		{
    295 			/* check if duplicate NAT ip */
    296 			if (nat_iface_ipv4_addr[j] == data->ipv4_addr)
    297 				break;
    298 
    299 			/* Cache the new nat iface address */
    300 			if (nat_iface_ipv4_addr[j] == 0)
    301 			{
    302 				nat_iface_ipv4_addr[j] = data->ipv4_addr;
    303 				iptodot("Nating connections of addr: ", nat_iface_ipv4_addr[j]);
    304 				break;
    305 			}
    306 		}
    307 
    308 		/* Add the cached temp entries to NAT table */
    309 		if (j != MAX_IFACE_ADDRESS)
    310 		{
    311 			nat_inst->ResetPwrSaveIf(data->ipv4_addr);
    312 			nat_inst->FlushTempEntries(data->ipv4_addr, true);
    313 		}
    314 	}
    315 	return;
    316 }
    317 
    318 void IPACM_ConntrackListener::HandleNeighIpAddrDelEvt(
    319    uint32_t ipv4_addr)
    320 {
    321 	int cnt;
    322 
    323 	if(ipv4_addr == 0)
    324 	{
    325 		IPACMDBG("Ignoring\n");
    326 		return;
    327 	}
    328 
    329 	iptodot("HandleNeighIpAddrDelEvt(): Received ip addr", ipv4_addr);
    330 	for(cnt = 0; cnt<MAX_IFACE_ADDRESS; cnt++)
    331 	{
    332 		if (nat_iface_ipv4_addr[cnt] == ipv4_addr)
    333 		{
    334 			IPACMDBG("Reseting ct nat iface, entry (%d) ", cnt);
    335 			iptodot("with ipv4 address", nat_iface_ipv4_addr[cnt]);
    336 			nat_iface_ipv4_addr[cnt] = 0;
    337 			nat_inst->FlushTempEntries(ipv4_addr, false);
    338 			nat_inst->DelEntriesOnClntDiscon(ipv4_addr);
    339 		}
    340 	}
    341 
    342 	return;
    343 }
    344 
    345 void IPACM_ConntrackListener::TriggerWANUp(void *in_param)
    346 {
    347 	 ipacm_event_iface_up *wanup_data = (ipacm_event_iface_up *)in_param;
    348 
    349 	 IPACMDBG_H("Recevied below information during wanup,\n");
    350 	 IPACMDBG_H("if_name:%s, ipv4_address:0x%x\n",
    351 						wanup_data->ifname, wanup_data->ipv4_addr);
    352 
    353 	 if(wanup_data->ipv4_addr == 0)
    354 	 {
    355 		 IPACMERR("Invalid ipv4 address,ignoring IPA_HANDLE_WAN_UP event\n");
    356 		 return;
    357 	 }
    358 
    359 	 if(isWanUp())
    360 	 {
    361 		 if (wan_ipaddr != wanup_data->ipv4_addr)
    362 			 TriggerWANDown(wan_ipaddr);
    363 		 else
    364 			 return;
    365 	 }
    366 
    367 	 WanUp = true;
    368 	 isStaMode = wanup_data->is_sta;
    369 	 IPACMDBG("isStaMode: %d\n", isStaMode);
    370 
    371 	 wan_ipaddr = wanup_data->ipv4_addr;
    372 	 memcpy(wan_ifname, wanup_data->ifname, sizeof(wan_ifname));
    373 
    374 	 if(nat_inst != NULL)
    375 	 {
    376 		 nat_inst->AddTable(wanup_data->ipv4_addr);
    377 	 }
    378 
    379 	 IPACMDBG("creating nat threads\n");
    380 	 CreateNatThreads();
    381 }
    382 
    383 int IPACM_ConntrackListener::CreateConnTrackThreads(void)
    384 {
    385 	int ret;
    386 	pthread_t tcp_thread = 0, udp_thread = 0;
    387 
    388 	if(isCTReg == false)
    389 	{
    390 		if(!tcp_thread)
    391 		{
    392 			ret = pthread_create(&tcp_thread, NULL, IPACM_ConntrackClient::TCPRegisterWithConnTrack, NULL);
    393 			if(0 != ret)
    394 			{
    395 				IPACMERR("unable to create TCP conntrack event listner thread\n");
    396 				PERROR("unable to create TCP conntrack\n");
    397 				return -1;
    398 			}
    399 
    400 			IPACMDBG("created TCP conntrack event listner thread\n");
    401 			if(pthread_setname_np(tcp_thread, "tcp ct listener") != 0)
    402 			{
    403 				IPACMERR("unable to set thread name\n");
    404 			}
    405 		}
    406 
    407 		if(!udp_thread)
    408 		{
    409 			ret = pthread_create(&udp_thread, NULL, IPACM_ConntrackClient::UDPRegisterWithConnTrack, NULL);
    410 			if(0 != ret)
    411 			{
    412 				IPACMERR("unable to create UDP conntrack event listner thread\n");
    413 				PERROR("unable to create UDP conntrack\n");
    414 				goto error;
    415 			}
    416 
    417 			IPACMDBG("created UDP conntrack event listner thread\n");
    418 			if(pthread_setname_np(udp_thread, "udp ct listener") != 0)
    419 			{
    420 				IPACMERR("unable to set thread name\n");
    421 			}
    422 		}
    423 
    424 		isCTReg = true;
    425 	}
    426 
    427 	return 0;
    428 
    429 error:
    430 	return -1;
    431 }
    432 int IPACM_ConntrackListener::CreateNatThreads(void)
    433 {
    434 	int ret;
    435 	pthread_t udpcto_thread = 0;
    436 
    437 	if(isNatThreadStart == false)
    438 	{
    439 		if(!udpcto_thread)
    440 		{
    441 			ret = pthread_create(&udpcto_thread, NULL, IPACM_ConntrackClient::UDPConnTimeoutUpdate, NULL);
    442 			if(0 != ret)
    443 			{
    444 				IPACMERR("unable to create udp conn timeout thread\n");
    445 				PERROR("unable to create udp conn timeout\n");
    446 				goto error;
    447 			}
    448 
    449 			IPACMDBG("created upd conn timeout thread\n");
    450 			if(pthread_setname_np(udpcto_thread, "udp conn timeout") != 0)
    451 			{
    452 				IPACMERR("unable to set thread name\n");
    453 			}
    454 		}
    455 
    456 		isNatThreadStart = true;
    457 	}
    458 	return 0;
    459 
    460 error:
    461 	return -1;
    462 }
    463 
    464 void IPACM_ConntrackListener::TriggerWANDown(uint32_t wan_addr)
    465 {
    466 	int ret = 0;
    467 	IPACMDBG_H("Deleting ipv4 nat table with");
    468 	IPACMDBG_H(" public ip address(0x%x): %d.%d.%d.%d\n", wan_addr,
    469 			((wan_addr>>24) & 0xFF), ((wan_addr>>16) & 0xFF),
    470 			((wan_addr>>8) & 0xFF), (wan_addr & 0xFF));
    471 
    472 	 if(nat_inst != NULL)
    473 	 {
    474 		 ret = nat_inst->DeleteTable(wan_addr);
    475 		 if (ret)
    476 			 return;
    477 
    478 		 WanUp = false;
    479 		 wan_ipaddr = 0;
    480 	 }
    481 }
    482 
    483 
    484 void ParseCTMessage(struct nf_conntrack *ct)
    485 {
    486 	 uint32_t status, timeout;
    487 	 IPACMDBG("Printing conntrack parameters\n");
    488 
    489 	 iptodot("ATTR_IPV4_SRC = ATTR_ORIG_IPV4_SRC:", nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC));
    490 	 iptodot("ATTR_IPV4_DST = ATTR_ORIG_IPV4_DST:", nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST));
    491 	 IPACMDBG("ATTR_PORT_SRC = ATTR_ORIG_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC));
    492 	 IPACMDBG("ATTR_PORT_DST = ATTR_ORIG_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST));
    493 
    494 	 iptodot("ATTR_REPL_IPV4_SRC:", nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC));
    495 	 iptodot("ATTR_REPL_IPV4_DST:", nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST));
    496 	 IPACMDBG("ATTR_REPL_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC));
    497 	 IPACMDBG("ATTR_REPL_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST));
    498 
    499 	 iptodot("ATTR_SNAT_IPV4:", nfct_get_attr_u32(ct, ATTR_SNAT_IPV4));
    500 	 iptodot("ATTR_DNAT_IPV4:", nfct_get_attr_u32(ct, ATTR_DNAT_IPV4));
    501 	 IPACMDBG("ATTR_SNAT_PORT: 0x%x\n", nfct_get_attr_u16(ct, ATTR_SNAT_PORT));
    502 	 IPACMDBG("ATTR_DNAT_PORT: 0x%x\n", nfct_get_attr_u16(ct, ATTR_DNAT_PORT));
    503 
    504 	 IPACMDBG("ATTR_MARK: 0x%x\n", nfct_get_attr_u32(ct, ATTR_MARK));
    505 	 IPACMDBG("ATTR_USE: 0x%x\n", nfct_get_attr_u32(ct, ATTR_USE));
    506 	 IPACMDBG("ATTR_ID: 0x%x\n", nfct_get_attr_u32(ct, ATTR_ID));
    507 
    508 	 status = nfct_get_attr_u32(ct, ATTR_STATUS);
    509 	 IPACMDBG("ATTR_STATUS: 0x%x\n", status);
    510 
    511 	 timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT);
    512 	 IPACMDBG("ATTR_TIMEOUT: 0x%x\n", timeout);
    513 
    514 	 if(IPS_SRC_NAT & status)
    515 	 {
    516 			IPACMDBG("IPS_SRC_NAT set\n");
    517 	 }
    518 
    519 	 if(IPS_DST_NAT & status)
    520 	 {
    521 			IPACMDBG("IPS_DST_NAT set\n");
    522 	 }
    523 
    524 	 if(IPS_SRC_NAT_DONE & status)
    525 	 {
    526 			IPACMDBG("IPS_SRC_NAT_DONE set\n");
    527 	 }
    528 
    529 	 if(IPS_DST_NAT_DONE & status)
    530 	 {
    531 			IPACMDBG(" IPS_DST_NAT_DONE set\n");
    532 	 }
    533 
    534 	 IPACMDBG("\n");
    535 	 return;
    536 }
    537 
    538 void ParseCTV6Message(struct nf_conntrack *ct)
    539 {
    540 	 uint32_t status, timeout;
    541 	 struct nfct_attr_grp_ipv6 orig_params;
    542 	 uint8_t l4proto, tcp_flags, tcp_state;
    543 
    544 	 IPACMDBG("Printing conntrack parameters\n");
    545 
    546 	 nfct_get_attr_grp(ct, ATTR_GRP_ORIG_IPV6, (void *)&orig_params);
    547 	 IPACMDBG("Orig src_v6_addr: 0x%08x%08x%08x%08x\n", orig_params.src[0], orig_params.src[1],
    548                 	orig_params.src[2], orig_params.src[3]);
    549 	IPACMDBG("Orig dst_v6_addr: 0x%08x%08x%08x%08x\n", orig_params.dst[0], orig_params.dst[1],
    550                 	orig_params.dst[2], orig_params.dst[3]);
    551 
    552 	 IPACMDBG("ATTR_PORT_SRC = ATTR_ORIG_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC));
    553 	 IPACMDBG("ATTR_PORT_DST = ATTR_ORIG_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST));
    554 
    555 	 IPACMDBG("ATTR_MARK: 0x%x\n", nfct_get_attr_u32(ct, ATTR_MARK));
    556 	 IPACMDBG("ATTR_USE: 0x%x\n", nfct_get_attr_u32(ct, ATTR_USE));
    557 	 IPACMDBG("ATTR_ID: 0x%x\n", nfct_get_attr_u32(ct, ATTR_ID));
    558 
    559 	 timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT);
    560 	 IPACMDBG("ATTR_TIMEOUT: 0x%x\n", timeout);
    561 
    562 	 status = nfct_get_attr_u32(ct, ATTR_STATUS);
    563 	 IPACMDBG("ATTR_STATUS: 0x%x\n", status);
    564 
    565 	 l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO);
    566 	 IPACMDBG("ATTR_ORIG_L4PROTO: 0x%x\n", l4proto);
    567 	 if(l4proto == IPPROTO_TCP)
    568 	 {
    569 		tcp_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE);
    570 		IPACMDBG("ATTR_TCP_STATE: 0x%x\n", tcp_state);
    571 
    572 		tcp_flags =  nfct_get_attr_u8(ct, ATTR_TCP_FLAGS_ORIG);
    573 		IPACMDBG("ATTR_TCP_FLAGS_ORIG: 0x%x\n", tcp_flags);
    574 	 }
    575 
    576 	 IPACMDBG("\n");
    577 	 return;
    578 }
    579 
    580 #ifdef CT_OPT
    581 void IPACM_ConntrackListener::ProcessCTV6Message(void *param)
    582 {
    583 	ipacm_ct_evt_data *evt_data = (ipacm_ct_evt_data *)param;
    584 	u_int8_t l4proto = 0;
    585 	uint32_t status = 0;
    586 	struct nf_conntrack *ct = evt_data->ct;
    587 
    588 #ifdef IPACM_DEBUG
    589 	 char buf[1024];
    590 
    591 	 /* Process message and generate ioctl call to kernel thread */
    592 	 nfct_snprintf(buf, sizeof(buf), evt_data->ct,
    593 								 evt_data->type, NFCT_O_PLAIN, NFCT_OF_TIME);
    594 	 IPACMDBG("%s\n", buf);
    595 	 IPACMDBG("\n");
    596 	 ParseCTV6Message(ct);
    597 #endif
    598 
    599 	if(p_lan2lan == NULL)
    600 	{
    601 		IPACMERR("Lan2Lan Instance is null\n");
    602 		goto IGNORE;
    603 	}
    604 
    605 	status = nfct_get_attr_u32(ct, ATTR_STATUS);
    606 	if((IPS_DST_NAT & status) || (IPS_SRC_NAT & status))
    607 	{
    608 		IPACMDBG("Either Destination or Source nat flag Set\n");
    609 		goto IGNORE;
    610 	}
    611 
    612 	l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO);
    613 	if(IPPROTO_UDP != l4proto && IPPROTO_TCP != l4proto)
    614 	{
    615 		 IPACMDBG("Received unexpected protocl %d conntrack message\n", l4proto);
    616 		 goto IGNORE;
    617 	}
    618 
    619 	IPACMDBG("Neither Destination nor Source nat flag Set\n");
    620 	struct nfct_attr_grp_ipv6 orig_params;
    621 	nfct_get_attr_grp(ct, ATTR_GRP_ORIG_IPV6, (void *)&orig_params);
    622 
    623 	ipacm_event_connection lan2lan_conn;
    624 	lan2lan_conn.iptype = IPA_IP_v6;
    625 	memcpy(lan2lan_conn.src_ipv6_addr, orig_params.src,
    626 				 sizeof(lan2lan_conn.src_ipv6_addr));
    627     IPACMDBG("Before convert, src_v6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.src_ipv6_addr[0], lan2lan_conn.src_ipv6_addr[1],
    628                 	lan2lan_conn.src_ipv6_addr[2], lan2lan_conn.src_ipv6_addr[3]);
    629     for(int cnt=0; cnt<4; cnt++)
    630 	{
    631 	   lan2lan_conn.src_ipv6_addr[cnt] = ntohl(lan2lan_conn.src_ipv6_addr[cnt]);
    632 	}
    633 	IPACMDBG("After convert src_v6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.src_ipv6_addr[0], lan2lan_conn.src_ipv6_addr[1],
    634                 	lan2lan_conn.src_ipv6_addr[2], lan2lan_conn.src_ipv6_addr[3]);
    635 
    636 	memcpy(lan2lan_conn.dst_ipv6_addr, orig_params.dst,
    637 				 sizeof(lan2lan_conn.dst_ipv6_addr));
    638 	IPACMDBG("Before convert, dst_ipv6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.dst_ipv6_addr[0], lan2lan_conn.dst_ipv6_addr[1],
    639                 	lan2lan_conn.dst_ipv6_addr[2], lan2lan_conn.dst_ipv6_addr[3]);
    640     for(int cnt=0; cnt<4; cnt++)
    641 	{
    642 	   lan2lan_conn.dst_ipv6_addr[cnt] = ntohl(lan2lan_conn.dst_ipv6_addr[cnt]);
    643 	}
    644 	IPACMDBG("After convert, dst_ipv6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.dst_ipv6_addr[0], lan2lan_conn.dst_ipv6_addr[1],
    645                 	lan2lan_conn.dst_ipv6_addr[2], lan2lan_conn.dst_ipv6_addr[3]);
    646 
    647 	if(((IPPROTO_UDP == l4proto) && (NFCT_T_NEW == evt_data->type)) ||
    648 		 ((IPPROTO_TCP == l4proto) &&
    649 			(nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_ESTABLISHED))
    650 		 )
    651 	{
    652 			p_lan2lan->handle_new_connection(&lan2lan_conn);
    653 	}
    654 	else if((IPPROTO_UDP == l4proto && NFCT_T_DESTROY == evt_data->type) ||
    655 					(IPPROTO_TCP == l4proto &&
    656 					 nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_FIN_WAIT))
    657 	{
    658 			p_lan2lan->handle_del_connection(&lan2lan_conn);
    659 	}
    660 
    661 IGNORE:
    662 	/* Cleanup item that was allocated during the original CT callback */
    663 	nfct_destroy(ct);
    664 	return;
    665 }
    666 #endif
    667 
    668 void IPACM_ConntrackListener::ProcessCTMessage(void *param)
    669 {
    670 	 ipacm_ct_evt_data *evt_data = (ipacm_ct_evt_data *)param;
    671 	 u_int8_t l4proto = 0;
    672 
    673 #ifdef IPACM_DEBUG
    674 	 char buf[1024];
    675 	 unsigned int out_flags;
    676 
    677 	 /* Process message and generate ioctl call to kernel thread */
    678 	 out_flags = (NFCT_OF_SHOW_LAYER3 | NFCT_OF_TIME | NFCT_OF_ID);
    679 	 nfct_snprintf(buf, sizeof(buf), evt_data->ct,
    680 								 evt_data->type, NFCT_O_PLAIN, out_flags);
    681 	 IPACMDBG_H("%s\n", buf);
    682 
    683 	 ParseCTMessage(evt_data->ct);
    684 #endif
    685 
    686 	 l4proto = nfct_get_attr_u8(evt_data->ct, ATTR_ORIG_L4PROTO);
    687 	 if(IPPROTO_UDP != l4proto && IPPROTO_TCP != l4proto)
    688 	 {
    689 			IPACMDBG("Received unexpected protocl %d conntrack message\n", l4proto);
    690 	 }
    691 	 else
    692 	 {
    693 			ProcessTCPorUDPMsg(evt_data->ct, evt_data->type, l4proto);
    694 	 }
    695 
    696 	 /* Cleanup item that was allocated during the original CT callback */
    697 	 nfct_destroy(evt_data->ct);
    698 	 return;
    699 }
    700 
    701 bool IPACM_ConntrackListener::AddIface(
    702    nat_table_entry *rule, bool *isTempEntry)
    703 {
    704 	int cnt;
    705 
    706 	*isTempEntry = false;
    707 
    708 	/* Special handling for Passthrough IP. */
    709 	if (IPACM_Iface::ipacmcfg->ipacm_ip_passthrough_mode)
    710 	{
    711 		if (rule->private_ip == IPACM_Wan::getWANIP())
    712 		{
    713 			IPACMDBG("In Passthrough mode and entry matched with Wan IP (0x%x)\n",
    714 				rule->private_ip);
    715 			return true;
    716 		}
    717 	}
    718 
    719 	/* check whether nat iface or not */
    720 	for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
    721 	{
    722 		if (nat_iface_ipv4_addr[cnt] != 0)
    723 		{
    724 			if (rule->private_ip == nat_iface_ipv4_addr[cnt] ||
    725 				rule->target_ip == nat_iface_ipv4_addr[cnt])
    726 			{
    727 				IPACMDBG("matched nat_iface_ipv4_addr entry(%d)\n", cnt);
    728 				iptodot("AddIface(): Nat entry match with ip addr",
    729 						nat_iface_ipv4_addr[cnt]);
    730 				return true;
    731 			}
    732 		}
    733 	}
    734 
    735 	if (!isStaMode)
    736 	{
    737 		/* check whether non nat iface or not, on Non Nat iface
    738 		   add dummy rule by copying public ip to private ip */
    739 		for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
    740 		{
    741 			if (nonnat_iface_ipv4_addr[cnt] != 0)
    742 			{
    743 				if (rule->private_ip == nonnat_iface_ipv4_addr[cnt] ||
    744 					rule->target_ip == nonnat_iface_ipv4_addr[cnt])
    745 				{
    746 					IPACMDBG("matched non_nat_iface_ipv4_addr entry(%d)\n", cnt);
    747 					iptodot("AddIface(): Non Nat entry match with ip addr",
    748 							nonnat_iface_ipv4_addr[cnt]);
    749 
    750 					rule->private_ip = rule->public_ip;
    751 					rule->private_port = rule->public_port;
    752 					return true;
    753 				}
    754 			}
    755 		}
    756 		IPACMDBG_H("Not mtaching with non-nat ifaces\n");
    757 	}
    758 	else
    759 		IPACMDBG("In STA mode, don't compare against non nat ifaces\n");
    760 
    761 	if(pConfig == NULL)
    762 	{
    763 		pConfig = IPACM_Config::GetInstance();
    764 		if(pConfig == NULL)
    765 		{
    766 			IPACMERR("Unable to get Config instance\n");
    767 			return false;
    768 		}
    769 	}
    770 
    771 	if (pConfig->isPrivateSubnet(rule->private_ip) ||
    772 		pConfig->isPrivateSubnet(rule->target_ip))
    773 	{
    774 		IPACMDBG("Matching with Private subnet\n");
    775 		*isTempEntry = true;
    776 		return true;
    777 	}
    778 
    779 	return false;
    780 }
    781 
    782 void IPACM_ConntrackListener::AddORDeleteNatEntry(const nat_entry_bundle *input)
    783 {
    784 	u_int8_t tcp_state;
    785 
    786 	if (nat_inst == NULL)
    787 	{
    788 		IPACMERR("Nat instance is NULL, unable to add or delete\n");
    789 		return;
    790 	}
    791 
    792 	IPACMDBG_H("Below Nat Entry will either be added or deleted\n");
    793 	iptodot("AddORDeleteNatEntry(): target ip or dst ip",
    794 			input->rule->target_ip);
    795 	IPACMDBG("target port or dst port: 0x%x Decimal:%d\n",
    796 			 input->rule->target_port, input->rule->target_port);
    797 	iptodot("AddORDeleteNatEntry(): private ip or src ip",
    798 			input->rule->private_ip);
    799 	IPACMDBG("private port or src port: 0x%x, Decimal:%d\n",
    800 			 input->rule->private_port, input->rule->private_port);
    801 	IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n",
    802 			 input->rule->public_port, input->rule->public_port);
    803 	IPACMDBG("Protocol: %d, destination nat flag: %d\n",
    804 			 input->rule->protocol, input->rule->dst_nat);
    805 
    806 	if (IPPROTO_TCP == input->rule->protocol)
    807 	{
    808 		tcp_state = nfct_get_attr_u8(input->ct, ATTR_TCP_STATE);
    809 		if (TCP_CONNTRACK_ESTABLISHED == tcp_state)
    810 		{
    811 			IPACMDBG("TCP state TCP_CONNTRACK_ESTABLISHED(%d)\n", tcp_state);
    812 			if (!CtList->isWanUp())
    813 			{
    814 				IPACMDBG("Wan is not up, cache connections\n");
    815 				nat_inst->CacheEntry(input->rule);
    816 			}
    817 			else if (input->isTempEntry)
    818 			{
    819 				nat_inst->AddTempEntry(input->rule);
    820 			}
    821 			else
    822 			{
    823 				nat_inst->AddEntry(input->rule);
    824 			}
    825 		}
    826 		else if (TCP_CONNTRACK_FIN_WAIT == tcp_state ||
    827 				   input->type == NFCT_T_DESTROY)
    828 		{
    829 			IPACMDBG("TCP state TCP_CONNTRACK_FIN_WAIT(%d) "
    830 					 "or type NFCT_T_DESTROY(%d)\n", tcp_state, input->type);
    831 
    832 			nat_inst->DeleteEntry(input->rule);
    833 			nat_inst->DeleteTempEntry(input->rule);
    834 		}
    835 		else
    836 		{
    837 			IPACMDBG("Ignore tcp state: %d and type: %d\n",
    838 					 tcp_state, input->type);
    839 		}
    840 
    841 	}
    842 	else if (IPPROTO_UDP == input->rule->protocol)
    843 	{
    844 		if (NFCT_T_NEW == input->type)
    845 		{
    846 			IPACMDBG("New UDP connection at time %ld\n", time(NULL));
    847 			if (!CtList->isWanUp())
    848 			{
    849 				IPACMDBG("Wan is not up, cache connections\n");
    850 				nat_inst->CacheEntry(input->rule);
    851 			}
    852 			else if (input->isTempEntry)
    853 			{
    854 				nat_inst->AddTempEntry(input->rule);
    855 			}
    856 			else
    857 			{
    858 				nat_inst->AddEntry(input->rule);
    859 			}
    860 		}
    861 		else if (NFCT_T_DESTROY == input->type)
    862 		{
    863 			IPACMDBG("UDP connection close at time %ld\n", time(NULL));
    864 			nat_inst->DeleteEntry(input->rule);
    865 			nat_inst->DeleteTempEntry(input->rule);
    866 		}
    867 	}
    868 
    869 	return;
    870 }
    871 
    872 void IPACM_ConntrackListener::PopulateTCPorUDPEntry(
    873 	 struct nf_conntrack *ct,
    874 	 uint32_t status,
    875 	 nat_table_entry *rule)
    876 {
    877 	if (IPS_DST_NAT == status)
    878 	{
    879 		IPACMDBG("Destination NAT\n");
    880 		rule->dst_nat = true;
    881 
    882 		IPACMDBG("Parse reply tuple\n");
    883 		rule->target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
    884 		rule->target_ip = ntohl(rule->target_ip);
    885 		iptodot("PopulateTCPorUDPEntry(): target ip", rule->target_ip);
    886 
    887 		/* Retriev target/dst port */
    888 		rule->target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
    889 		rule->target_port = ntohs(rule->target_port);
    890 		if (0 == rule->target_port)
    891 		{
    892 			IPACMDBG("unable to retrieve target port\n");
    893 		}
    894 
    895 		rule->public_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
    896 		rule->public_port = ntohs(rule->public_port);
    897 
    898 		/* Retriev src/private ip address */
    899 		rule->private_ip = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC);
    900 		rule->private_ip = ntohl(rule->private_ip);
    901 		iptodot("PopulateTCPorUDPEntry(): private ip", rule->private_ip);
    902 		if (0 == rule->private_ip)
    903 		{
    904 			IPACMDBG("unable to retrieve private ip address\n");
    905 		}
    906 
    907 		/* Retriev src/private port */
    908 		rule->private_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC);
    909 		rule->private_port = ntohs(rule->private_port);
    910 		if (0 == rule->private_port)
    911 		{
    912 			IPACMDBG("unable to retrieve private port\n");
    913 		}
    914 	}
    915 	else if (IPS_SRC_NAT == status)
    916 	{
    917 		IPACMDBG("Source NAT\n");
    918 		rule->dst_nat = false;
    919 
    920 		/* Retriev target/dst ip address */
    921 		IPACMDBG("Parse source tuple\n");
    922 		rule->target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST);
    923 		rule->target_ip = ntohl(rule->target_ip);
    924 		iptodot("PopulateTCPorUDPEntry(): target ip", rule->target_ip);
    925 		if (0 == rule->target_ip)
    926 		{
    927 			IPACMDBG("unable to retrieve target ip address\n");
    928 		}
    929 		/* Retriev target/dst port */
    930 		rule->target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
    931 		rule->target_port = ntohs(rule->target_port);
    932 		if (0 == rule->target_port)
    933 		{
    934 			IPACMDBG("unable to retrieve target port\n");
    935 		}
    936 
    937 		/* Retriev public port */
    938 		rule->public_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST);
    939 		rule->public_port = ntohs(rule->public_port);
    940 		if (0 == rule->public_port)
    941 		{
    942 			IPACMDBG("unable to retrieve public port\n");
    943 		}
    944 
    945 		/* Retriev src/private ip address */
    946 		rule->private_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
    947 		rule->private_ip = ntohl(rule->private_ip);
    948 		iptodot("PopulateTCPorUDPEntry(): private ip", rule->private_ip);
    949 		if (0 == rule->private_ip)
    950 		{
    951 			IPACMDBG("unable to retrieve private ip address\n");
    952 		}
    953 
    954 		/* Retriev src/private port */
    955 		rule->private_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
    956 		rule->private_port = ntohs(rule->private_port);
    957 		if (0 == rule->private_port)
    958 		{
    959 			IPACMDBG("unable to retrieve private port\n");
    960 		}
    961 	}
    962 
    963 	return;
    964 }
    965 
    966 #ifdef CT_OPT
    967 void IPACM_ConntrackListener::HandleLan2Lan(struct nf_conntrack *ct,
    968 	enum nf_conntrack_msg_type type,
    969 	 nat_table_entry *rule)
    970 {
    971 	ipacm_event_connection lan2lan_conn = { 0 };
    972 
    973 	if (p_lan2lan == NULL)
    974 	{
    975 		IPACMERR("Lan2Lan Instance is null\n");
    976 		return;
    977 	}
    978 
    979 	lan2lan_conn.iptype = IPA_IP_v4;
    980 	lan2lan_conn.src_ipv4_addr = orig_src_ip;
    981 	lan2lan_conn.dst_ipv4_addr = orig_dst_ip;
    982 
    983 	if (((IPPROTO_UDP == rule->protocol) && (NFCT_T_NEW == type)) ||
    984 		((IPPROTO_TCP == rule->protocol) && (nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_ESTABLISHED)))
    985 	{
    986 		p_lan2lan->handle_new_connection(&lan2lan_conn);
    987 	}
    988 	else if ((IPPROTO_UDP == rule->protocol && NFCT_T_DESTROY == type) ||
    989 			   (IPPROTO_TCP == rule->protocol &&
    990 				nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_FIN_WAIT))
    991 	{
    992 		p_lan2lan->handle_del_connection(&lan2lan_conn);
    993 	}
    994 }
    995 #endif
    996 
    997 void IPACM_ConntrackListener::CheckSTAClient(
    998    const nat_table_entry *rule, bool *isTempEntry)
    999 {
   1000 	int nCnt;
   1001 
   1002 	/* Check whether target is in STA client list or not
   1003       if not ignore the connection */
   1004 	 if(!isStaMode || (StaClntCnt == 0))
   1005 	 {
   1006 		return;
   1007 	 }
   1008 
   1009 	 if((sta_clnt_ipv4_addr[0] & STA_CLNT_SUBNET_MASK) !=
   1010 		 (rule->target_ip & STA_CLNT_SUBNET_MASK))
   1011 	 {
   1012 		IPACMDBG("STA client subnet mask not matching\n");
   1013 		return;
   1014 	 }
   1015 
   1016 	 IPACMDBG("StaClntCnt %d\n", StaClntCnt);
   1017 	 for(nCnt = 0; nCnt < StaClntCnt; nCnt++)
   1018 	 {
   1019 		IPACMDBG("Comparing trgt_ip 0x%x with sta clnt ip: 0x%x\n",
   1020 			 rule->target_ip, sta_clnt_ipv4_addr[nCnt]);
   1021 		if(rule->target_ip == sta_clnt_ipv4_addr[nCnt])
   1022 		{
   1023 			IPACMDBG("Match index %d\n", nCnt);
   1024 			return;
   1025 		}
   1026 	 }
   1027 
   1028 	IPACMDBG_H("Not matching with STA Clnt Ip Addrs 0x%x\n",
   1029 		rule->target_ip);
   1030 	*isTempEntry = true;
   1031 }
   1032 
   1033 /* conntrack send in host order and ipa expects in host order */
   1034 void IPACM_ConntrackListener::ProcessTCPorUDPMsg(
   1035 	 struct nf_conntrack *ct,
   1036 	 enum nf_conntrack_msg_type type,
   1037 	 u_int8_t l4proto)
   1038 {
   1039 	 nat_table_entry rule;
   1040 	 uint32_t status = 0;
   1041 	 uint32_t orig_src_ip, orig_dst_ip;
   1042 	 bool isAdd = false;
   1043 
   1044 	 nat_entry_bundle nat_entry;
   1045 	 nat_entry.isTempEntry = false;
   1046 	 nat_entry.ct = ct;
   1047 	 nat_entry.type = type;
   1048 
   1049  	 memset(&rule, 0, sizeof(rule));
   1050 	 IPACMDBG("Received type:%d with proto:%d\n", type, l4proto);
   1051 	 status = nfct_get_attr_u32(ct, ATTR_STATUS);
   1052 
   1053 	 /* Retrieve Protocol */
   1054 	 rule.protocol = nfct_get_attr_u8(ct, ATTR_REPL_L4PROTO);
   1055 
   1056 	 if(IPS_DST_NAT & status)
   1057 	 {
   1058 		 status = IPS_DST_NAT;
   1059 	 }
   1060 	 else if(IPS_SRC_NAT & status)
   1061 	 {
   1062 		 status = IPS_SRC_NAT;
   1063 	 }
   1064 	 else
   1065 	 {
   1066 		 IPACMDBG("Neither Destination nor Source nat flag Set\n");
   1067 		 orig_src_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
   1068 		 orig_src_ip = ntohl(orig_src_ip);
   1069 		 if(orig_src_ip == 0)
   1070 		 {
   1071 			 IPACMERR("unable to retrieve orig src ip address\n");
   1072 			 return;
   1073 		 }
   1074 
   1075 		 orig_dst_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST);
   1076 		 orig_dst_ip = ntohl(orig_dst_ip);
   1077 		 if(orig_dst_ip == 0)
   1078 		 {
   1079 			 IPACMERR("unable to retrieve orig dst ip address\n");
   1080 			 return;
   1081 		 }
   1082 
   1083 		if(orig_src_ip == wan_ipaddr)
   1084 		{
   1085 			IPACMDBG("orig src ip:0x%x equal to wan ip\n",orig_src_ip);
   1086 			status = IPS_SRC_NAT;
   1087 		}
   1088 		else if(orig_dst_ip == wan_ipaddr)
   1089 		{
   1090 			IPACMDBG("orig Dst IP:0x%x equal to wan ip\n",orig_dst_ip);
   1091 			status = IPS_DST_NAT;
   1092 		}
   1093 		else
   1094 		{
   1095 			IPACMDBG_H("Neither orig src ip:0x%x Nor orig Dst IP:0x%x equal to wan ip:0x%x\n",
   1096 					   orig_src_ip, orig_dst_ip, wan_ipaddr);
   1097 
   1098 #ifdef CT_OPT
   1099 			HandleLan2Lan(ct, type, &rule);
   1100 #endif
   1101 			return;
   1102 		}
   1103 	 }
   1104 
   1105 	 if(IPS_DST_NAT == status || IPS_SRC_NAT == status)
   1106 	 {
   1107 		 PopulateTCPorUDPEntry(ct, status, &rule);
   1108 		 rule.public_ip = wan_ipaddr;
   1109 	 }
   1110 	 else
   1111 	 {
   1112 		 IPACMDBG("Neither source Nor destination nat\n");
   1113 		 goto IGNORE;
   1114 	 }
   1115 
   1116 	 if (rule.private_ip != wan_ipaddr)
   1117 	 {
   1118 		 isAdd = AddIface(&rule, &nat_entry.isTempEntry);
   1119 		 if (!isAdd)
   1120 		 {
   1121 			 goto IGNORE;
   1122 		 }
   1123 	 }
   1124 	 else
   1125 	 {
   1126 		 if (isStaMode)
   1127 		 {
   1128 			 IPACMDBG("In STA mode, ignore connections destinated to STA interface\n");
   1129 			 goto IGNORE;
   1130 		 }
   1131 
   1132 		 IPACMDBG("For embedded connections add dummy nat rule\n");
   1133 		 IPACMDBG("Change private port %d to %d\n",
   1134 				  rule.private_port, rule.public_port);
   1135 		 rule.private_port = rule.public_port;
   1136 	 }
   1137 
   1138 	 CheckSTAClient(&rule, &nat_entry.isTempEntry);
   1139 	 nat_entry.rule = &rule;
   1140 	 AddORDeleteNatEntry(&nat_entry);
   1141 	 return;
   1142 
   1143 IGNORE:
   1144 	IPACMDBG_H("ignoring below Nat Entry\n");
   1145 	iptodot("ProcessTCPorUDPMsg(): target ip or dst ip", rule.target_ip);
   1146 	IPACMDBG("target port or dst port: 0x%x Decimal:%d\n", rule.target_port, rule.target_port);
   1147 	iptodot("ProcessTCPorUDPMsg(): private ip or src ip", rule.private_ip);
   1148 	IPACMDBG("private port or src port: 0x%x, Decimal:%d\n", rule.private_port, rule.private_port);
   1149 	IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n", rule.public_port, rule.public_port);
   1150 	IPACMDBG("Protocol: %d, destination nat flag: %d\n", rule.protocol, rule.dst_nat);
   1151 	return;
   1152 }
   1153 
   1154 void IPACM_ConntrackListener::HandleSTAClientAddEvt(uint32_t clnt_ip_addr)
   1155 {
   1156 	 int cnt;
   1157 	 IPACMDBG_H("Received STA client 0x%x\n", clnt_ip_addr);
   1158 
   1159 	 if(StaClntCnt >= MAX_STA_CLNT_IFACES)
   1160 	 {
   1161 		IPACMDBG("Max STA client reached, ignore 0x%x\n", clnt_ip_addr);
   1162 		return;
   1163 	 }
   1164 
   1165 	 for(cnt=0; cnt<MAX_STA_CLNT_IFACES; cnt++)
   1166 	 {
   1167 		if(sta_clnt_ipv4_addr[cnt] != 0 &&
   1168 		 sta_clnt_ipv4_addr[cnt] == clnt_ip_addr)
   1169 		{
   1170 			IPACMDBG("Ignoring duplicate one 0x%x\n", clnt_ip_addr);
   1171 			break;
   1172 		}
   1173 
   1174 		if(sta_clnt_ipv4_addr[cnt] == 0)
   1175 		{
   1176 			IPACMDBG("Adding STA client 0x%x at Index: %d\n",
   1177 					clnt_ip_addr, cnt);
   1178 			sta_clnt_ipv4_addr[cnt] = clnt_ip_addr;
   1179 			StaClntCnt++;
   1180 			IPACMDBG("STA client cnt %d\n", StaClntCnt);
   1181 			break;
   1182 		}
   1183 
   1184 	 }
   1185 
   1186 	 nat_inst->FlushTempEntries(clnt_ip_addr, true);
   1187 	 return;
   1188 }
   1189 
   1190 void IPACM_ConntrackListener::HandleSTAClientDelEvt(uint32_t clnt_ip_addr)
   1191 {
   1192 	 int cnt;
   1193 	 IPACMDBG_H("Received STA client 0x%x\n", clnt_ip_addr);
   1194 
   1195 	 for(cnt=0; cnt<MAX_STA_CLNT_IFACES; cnt++)
   1196 	 {
   1197 		if(sta_clnt_ipv4_addr[cnt] != 0 &&
   1198 		 sta_clnt_ipv4_addr[cnt] == clnt_ip_addr)
   1199 		{
   1200 			IPACMDBG("Deleting STA client 0x%x at index: %d\n",
   1201 					clnt_ip_addr, cnt);
   1202 			sta_clnt_ipv4_addr[cnt] = 0;
   1203 			nat_inst->DelEntriesOnSTAClntDiscon(clnt_ip_addr);
   1204 			StaClntCnt--;
   1205 			IPACMDBG("STA client cnt %d\n", StaClntCnt);
   1206 			break;
   1207 		}
   1208 	 }
   1209 
   1210 	 nat_inst->FlushTempEntries(clnt_ip_addr, false);
   1211    return;
   1212 }
   1213