1/*
2Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
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
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF 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
39IPACM_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
71void 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
142int 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
226void 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
284void 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
318void 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
345void 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
383int 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
429error:
430	return -1;
431}
432int 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
460error:
461	return -1;
462}
463
464void 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
484void 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
538void 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
581void 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
661IGNORE:
662	/* Cleanup item that was allocated during the original CT callback */
663	nfct_destroy(ct);
664	return;
665}
666#endif
667
668void 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
701bool 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
782void 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
872void 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
967void 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
997void 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 */
1034void 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
1143IGNORE:
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
1154void 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
1190void 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