1 /*
2 Copyright (c) 2013-2020, 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 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
39 
IPACM_ConntrackListener()40 IPACM_ConntrackListener::IPACM_ConntrackListener()
41 {
42 	 IPACMDBG("\n");
43 	 isNatThreadStart = false;
44 	 isCTReg = false;
45 	 WanUp = false;
46 	 isReadCTDone = false;
47 	 isProcessCTDone = false;
48 	 nat_inst = NatApp::GetInstance();
49 
50 	 NatIfaceCnt = 0;
51 	 StaClntCnt = 0;
52 	 pNatIfaces = NULL;
53 	 ct_entries = NULL;
54 	 pConfig = IPACM_Config::GetInstance();;
55 
56 	 memset(nat_iface_ipv4_addr, 0, sizeof(nat_iface_ipv4_addr));
57 	 memset(nonnat_iface_ipv4_addr, 0, sizeof(nonnat_iface_ipv4_addr));
58 	 memset(sta_clnt_ipv4_addr, 0, sizeof(sta_clnt_ipv4_addr));
59 
60 	 IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, this);
61 	 IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, this);
62 	 IPACM_EvtDispatcher::registr(IPA_PROCESS_CT_MESSAGE, this);
63 	 IPACM_EvtDispatcher::registr(IPA_PROCESS_CT_MESSAGE_V6, this);
64 	 IPACM_EvtDispatcher::registr(IPA_HANDLE_WLAN_UP, this);
65 	 IPACM_EvtDispatcher::registr(IPA_HANDLE_LAN_UP, this);
66 	 IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, this);
67 	 IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, this);
68 
69 #ifdef CT_OPT
70 	 p_lan2lan = IPACM_LanToLan::getLan2LanInstance();
71 #endif
72 
73 	 /* Initialize the CT cache. */
74 	 memset(ct_cache, 0, sizeof(ct_cache));
75 }
76 
event_callback(ipa_cm_event_id evt,void * data)77 void IPACM_ConntrackListener::event_callback(ipa_cm_event_id evt,
78 						void *data)
79 {
80 	 ipacm_event_iface_up *wan_down = NULL;
81 
82 	 if(data == NULL)
83 	 {
84 		 IPACMERR("Invalid Data\n");
85 		 return;
86 	 }
87 
88 	 switch(evt)
89 	 {
90 	 case IPA_PROCESS_CT_MESSAGE:
91 			IPACMDBG("Received IPA_PROCESS_CT_MESSAGE event\n");
92 			ProcessCTMessage(data);
93 			break;
94 
95 #ifdef CT_OPT
96 	 case IPA_PROCESS_CT_MESSAGE_V6:
97 			IPACMDBG("Received IPA_PROCESS_CT_MESSAGE_V6 event\n");
98 			ProcessCTV6Message(data);
99 			break;
100 #endif
101 
102 	 case IPA_HANDLE_WAN_UP:
103 			IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n");
104 			CreateConnTrackThreads();
105 			TriggerWANUp(data);
106 			if(isReadCTDone && !isProcessCTDone)
107 			{
108 				processConntrack();
109 			}
110 			/* Process the cached entries. */
111 			processCacheConntrack();
112 			break;
113 
114 	 case IPA_HANDLE_WAN_DOWN:
115 			IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN event\n");
116 			wan_down = (ipacm_event_iface_up *)data;
117 			if(isWanUp())
118 			{
119 				TriggerWANDown(wan_down->ipv4_addr);
120 			}
121 			break;
122 
123 	/* if wlan or lan comes up after wan interface, modify
124 		 tcp/udp filters to ignore local wlan or lan connections */
125 	 case IPA_HANDLE_WLAN_UP:
126 	 case IPA_HANDLE_LAN_UP:
127 			IPACMDBG_H("Received event: %d with ifname: %s and address: 0x%x\n",
128 							 evt, ((ipacm_event_iface_up *)data)->ifname,
129 							 ((ipacm_event_iface_up *)data)->ipv4_addr);
130 			if(isWanUp())
131 			{
132 				CreateConnTrackThreads();
133 				IPACM_ConntrackClient::UpdateUDPFilters(data, false);
134 				IPACM_ConntrackClient::UpdateTCPFilters(data, false);
135 			}
136 			break;
137 
138 	 case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT:
139 		 IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT event\n");
140 		 HandleNonNatIPAddr(data, true);
141 		 break;
142 
143 	 case IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT:
144 		 IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT event\n");
145 		 HandleNonNatIPAddr(data, false);
146 		 break;
147 
148 	 default:
149 			IPACMDBG("Ignore cmd %d\n", evt);
150 			break;
151 	 }
152 }
153 
CheckNatIface(ipacm_event_data_all * data,bool * NatIface)154 int IPACM_ConntrackListener::CheckNatIface(
155    ipacm_event_data_all *data, bool *NatIface)
156 {
157 	int fd = 0, len = 0, cnt, i;
158 	struct ifreq ifr;
159 	*NatIface = false;
160 
161 	if (data->ipv4_addr == 0 || data->iptype != IPA_IP_v4)
162 	{
163 		IPACMDBG("Ignoring\n");
164 		return IPACM_FAILURE;
165 	}
166 
167 	IPACMDBG("Received interface index %d with ip type: %d", data->if_index, data->iptype);
168 	iptodot(" and ipv4 address", data->ipv4_addr);
169 
170 	if (pConfig == NULL)
171 	{
172 		pConfig = IPACM_Config::GetInstance();
173 		if (pConfig == NULL)
174 		{
175 			IPACMERR("Unable to get Config instance\n");
176 			return IPACM_FAILURE;
177 		}
178 	}
179 
180 	cnt = pConfig->GetNatIfacesCnt();
181 	NatIfaceCnt = cnt;
182 	IPACMDBG("Total Nat ifaces: %d\n", NatIfaceCnt);
183 	if (pNatIfaces != NULL)
184 	{
185 		free(pNatIfaces);
186 		pNatIfaces = NULL;
187 	}
188 
189 	len = (sizeof(NatIfaces) * NatIfaceCnt);
190 	pNatIfaces = (NatIfaces *)malloc(len);
191 	if (pNatIfaces == NULL)
192 	{
193 		IPACMERR("Unable to allocate memory for non nat ifaces\n");
194 		return IPACM_FAILURE;
195 	}
196 
197 	memset(pNatIfaces, 0, len);
198 	if (pConfig->GetNatIfaces(NatIfaceCnt, pNatIfaces) != 0)
199 	{
200 		IPACMERR("Unable to retrieve non nat ifaces\n");
201 		return IPACM_FAILURE;
202 	}
203 
204 	/* Search/Configure linux interface-index and map it to IPA interface-index */
205 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
206 	{
207 		PERROR("get interface name socket create failed");
208 		return IPACM_FAILURE;
209 	}
210 
211 	memset(&ifr, 0, sizeof(struct ifreq));
212 	ifr.ifr_ifindex = data->if_index;
213 	if (ioctl(fd, SIOCGIFNAME, &ifr) < 0)
214 	{
215 		PERROR("call_ioctl_on_dev: ioctl failed:");
216 		close(fd);
217 		return IPACM_FAILURE;
218 	}
219 	close(fd);
220 
221 	for (i = 0; i < NatIfaceCnt; i++)
222 	{
223 		if (strncmp(ifr.ifr_name,
224 					pNatIfaces[i].iface_name,
225 					sizeof(pNatIfaces[i].iface_name)) == 0)
226 		{
227 			IPACMDBG_H("Nat iface (%s), entry (%d), dont cache",
228 						pNatIfaces[i].iface_name, i);
229 			iptodot("with ipv4 address: ", nat_iface_ipv4_addr[i]);
230 			*NatIface = true;
231 			return IPACM_SUCCESS;
232 		}
233 	}
234 
235 	return IPACM_SUCCESS;
236 }
237 
HandleNonNatIPAddr(void * inParam,bool AddOp)238 void IPACM_ConntrackListener::HandleNonNatIPAddr(
239    void *inParam, bool AddOp)
240 {
241 	ipacm_event_data_all *data = (ipacm_event_data_all *)inParam;
242 	bool NatIface = false;
243 	int cnt, ret;
244 
245 	if (backhaul_mode != Q6_WAN)
246 	{
247 		IPACMDBG("In STA mode, don't add dummy rules for non nat ifaces\n");
248 		return;
249 	}
250 
251 	/* Handle only non nat ifaces, NAT iface should be handle
252 	   separately to avoid race conditions between route/nat
253 	   rules add/delete operations */
254 	if (AddOp)
255 	{
256 		ret = CheckNatIface(data, &NatIface);
257 		if (!NatIface && ret == IPACM_SUCCESS)
258 		{
259 			/* Cache the non nat iface ip address */
260 			for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
261 			{
262 				if (nonnat_iface_ipv4_addr[cnt] == 0)
263 				{
264 					nonnat_iface_ipv4_addr[cnt] = data->ipv4_addr;
265 					IPACMDBG("Add ip addr to non nat list (%d) ", cnt);
266 					iptodot("with ipv4 address", nonnat_iface_ipv4_addr[cnt]);
267 
268 					/* Add dummy nat rule for non nat ifaces */
269 					nat_inst->FlushTempEntries(data->ipv4_addr, true, true);
270 					return;
271 				}
272 			}
273 		}
274 	}
275 	else
276 	{
277 		/* for delete operation */
278 		for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
279 		{
280 			if (nonnat_iface_ipv4_addr[cnt] == data->ipv4_addr)
281 			{
282 				IPACMDBG("Reseting ct filters, entry (%d) ", cnt);
283 				iptodot("with ipv4 address", nonnat_iface_ipv4_addr[cnt]);
284 				nonnat_iface_ipv4_addr[cnt] = 0;
285 				nat_inst->FlushTempEntries(data->ipv4_addr, false);
286 				nat_inst->DelEntriesOnClntDiscon(data->ipv4_addr);
287 				return;
288 			}
289 		}
290 
291 	}
292 
293 	return;
294 }
295 
HandleNeighIpAddrAddEvt(ipacm_event_data_all * data)296 void IPACM_ConntrackListener::HandleNeighIpAddrAddEvt(
297    ipacm_event_data_all *data)
298 {
299 	bool NatIface = false;
300 	int j, ret;
301 
302 	ret = CheckNatIface(data, &NatIface);
303 	if (NatIface && ret == IPACM_SUCCESS)
304 	{
305 		for (j = 0; j < MAX_IFACE_ADDRESS; j++)
306 		{
307 			/* check if duplicate NAT ip */
308 			if (nat_iface_ipv4_addr[j] == data->ipv4_addr)
309 				break;
310 
311 			/* Cache the new nat iface address */
312 			if (nat_iface_ipv4_addr[j] == 0)
313 			{
314 				nat_iface_ipv4_addr[j] = data->ipv4_addr;
315 				iptodot("Nating connections of addr: ", nat_iface_ipv4_addr[j]);
316 				break;
317 			}
318 		}
319 
320 		/* Add the cached temp entries to NAT table */
321 		if (j != MAX_IFACE_ADDRESS)
322 		{
323 			nat_inst->ResetPwrSaveIf(data->ipv4_addr);
324 			nat_inst->FlushTempEntries(data->ipv4_addr, true);
325 		}
326 	}
327 	return;
328 }
329 
HandleNeighIpAddrDelEvt(uint32_t ipv4_addr)330 void IPACM_ConntrackListener::HandleNeighIpAddrDelEvt(
331    uint32_t ipv4_addr)
332 {
333 	int cnt;
334 
335 	if(ipv4_addr == 0)
336 	{
337 		IPACMDBG("Ignoring\n");
338 		return;
339 	}
340 
341 	iptodot("HandleNeighIpAddrDelEvt(): Received ip addr", ipv4_addr);
342 	for(cnt = 0; cnt<MAX_IFACE_ADDRESS; cnt++)
343 	{
344 		if (nat_iface_ipv4_addr[cnt] == ipv4_addr)
345 		{
346 			IPACMDBG("Reseting ct nat iface, entry (%d) ", cnt);
347 			iptodot("with ipv4 address", nat_iface_ipv4_addr[cnt]);
348 			nat_iface_ipv4_addr[cnt] = 0;
349 			nat_inst->FlushTempEntries(ipv4_addr, false);
350 			nat_inst->DelEntriesOnClntDiscon(ipv4_addr);
351 		}
352 	}
353 
354 	return;
355 }
356 
TriggerWANUp(void * in_param)357 void IPACM_ConntrackListener::TriggerWANUp(void *in_param)
358 {
359 	 ipacm_event_iface_up *wanup_data = (ipacm_event_iface_up *)in_param;
360 	 uint8_t mux_id;
361 
362 	 IPACMDBG_H("Recevied below information during wanup,\n");
363 	 IPACMDBG_H("if_name:%s, ipv4_address:0x%x mux_id:%d, xlat_mux_id:%d\n",
364 						wanup_data->ifname, wanup_data->ipv4_addr,
365 						wanup_data->mux_id,
366 						wanup_data->xlat_mux_id);
367 
368 	 if(wanup_data->ipv4_addr == 0)
369 	 {
370 		 IPACMERR("Invalid ipv4 address,ignoring IPA_HANDLE_WAN_UP event\n");
371 		 return;
372 	 }
373 
374 	 if(isWanUp())
375 	 {
376 		 if (wan_ipaddr != wanup_data->ipv4_addr)
377 			 TriggerWANDown(wan_ipaddr);
378 		 else
379 			 return;
380 	 }
381 
382 	 WanUp = true;
383 	 backhaul_mode = wanup_data->backhaul_type;
384 	 IPACMDBG("backhaul_mode: %d\n", backhaul_mode);
385 
386 	 wan_ipaddr = wanup_data->ipv4_addr;
387 	 memcpy(wan_ifname, wanup_data->ifname, sizeof(wan_ifname));
388 
389 	 if(nat_inst != NULL)
390 	 {
391 		 if (wanup_data->mux_id == 0)
392 		   mux_id = wanup_data->xlat_mux_id;
393 		 else
394 		   mux_id = wanup_data->mux_id;
395 		 nat_inst->AddTable(wanup_data->ipv4_addr, mux_id);
396 	 }
397 
398 	 IPACMDBG("creating nat threads\n");
399 	 CreateNatThreads();
400 }
401 
CreateConnTrackThreads(void)402 int IPACM_ConntrackListener::CreateConnTrackThreads(void)
403 {
404 	int ret;
405 	pthread_t tcp_thread = 0, udp_thread = 0;
406 
407 	if(isCTReg == false)
408 	{
409 		ret = pthread_create(&tcp_thread, NULL, IPACM_ConntrackClient::TCPRegisterWithConnTrack, NULL);
410 		if(0 != ret)
411 		{
412 			IPACMERR("unable to create TCP conntrack event listner thread\n");
413 			PERROR("unable to create TCP conntrack\n");
414 			goto error;
415 		}
416 
417 		IPACMDBG("created TCP conntrack event listner thread\n");
418 		if(pthread_setname_np(tcp_thread, "tcp ct listener") != 0)
419 		{
420 			IPACMERR("unable to set thread name\n");
421 		}
422 
423 		ret = pthread_create(&udp_thread, NULL, IPACM_ConntrackClient::UDPRegisterWithConnTrack, NULL);
424 		if(0 != ret)
425 		{
426 			IPACMERR("unable to create UDP conntrack event listner thread\n");
427 			PERROR("unable to create UDP conntrack\n");
428 			goto error;
429 		}
430 
431 		IPACMDBG("created UDP conntrack event listner thread\n");
432 		if(pthread_setname_np(udp_thread, "udp ct listener") != 0)
433 		{
434 			IPACMERR("unable to set thread name\n");
435 		}
436 
437 		isCTReg = true;
438 	}
439 
440 	return 0;
441 
442 error:
443 	return -1;
444 }
CreateNatThreads(void)445 int IPACM_ConntrackListener::CreateNatThreads(void)
446 {
447 	int ret;
448 	pthread_t udpcto_thread = 0;
449 
450 	if(isNatThreadStart == false)
451 	{
452 		ret = pthread_create(&udpcto_thread, NULL, IPACM_ConntrackClient::UDPConnTimeoutUpdate, NULL);
453 		if(0 != ret)
454 		{
455 			IPACMERR("unable to create udp conn timeout thread\n");
456 			PERROR("unable to create udp conn timeout\n");
457 			goto error;
458 		}
459 
460 		IPACMDBG("created upd conn timeout thread\n");
461 		if(pthread_setname_np(udpcto_thread, "udp conn timeout") != 0)
462 		{
463 			IPACMERR("unable to set thread name\n");
464 		}
465 
466 		isNatThreadStart = true;
467 	}
468 	return 0;
469 
470 error:
471 	return -1;
472 }
473 
TriggerWANDown(uint32_t wan_addr)474 void IPACM_ConntrackListener::TriggerWANDown(uint32_t wan_addr)
475 {
476 	int ret = 0;
477 	IPACMDBG_H("Deleting ipv4 nat table with");
478 	IPACMDBG_H(" public ip address(0x%x): %d.%d.%d.%d\n", wan_addr,
479 			((wan_addr>>24) & 0xFF), ((wan_addr>>16) & 0xFF),
480 			((wan_addr>>8) & 0xFF), (wan_addr & 0xFF));
481 
482 	 if(nat_inst != NULL)
483 	 {
484 		 ret = nat_inst->DeleteTable(wan_addr);
485 		 if (ret)
486 			 return;
487 
488 		 WanUp = false;
489 		 wan_ipaddr = 0;
490 	 }
491 }
492 
493 
ParseCTMessage(struct nf_conntrack * ct)494 void ParseCTMessage(struct nf_conntrack *ct)
495 {
496 	 uint32_t status, timeout;
497 	 IPACMDBG("Printing conntrack parameters\n");
498 
499 	 iptodot("ATTR_IPV4_SRC = ATTR_ORIG_IPV4_SRC:", nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC));
500 	 iptodot("ATTR_IPV4_DST = ATTR_ORIG_IPV4_DST:", nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST));
501 	 IPACMDBG("ATTR_PORT_SRC = ATTR_ORIG_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC));
502 	 IPACMDBG("ATTR_PORT_DST = ATTR_ORIG_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST));
503 
504 	 iptodot("ATTR_REPL_IPV4_SRC:", nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC));
505 	 iptodot("ATTR_REPL_IPV4_DST:", nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST));
506 	 IPACMDBG("ATTR_REPL_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC));
507 	 IPACMDBG("ATTR_REPL_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST));
508 
509 	 iptodot("ATTR_SNAT_IPV4:", nfct_get_attr_u32(ct, ATTR_SNAT_IPV4));
510 	 iptodot("ATTR_DNAT_IPV4:", nfct_get_attr_u32(ct, ATTR_DNAT_IPV4));
511 	 IPACMDBG("ATTR_SNAT_PORT: 0x%x\n", nfct_get_attr_u16(ct, ATTR_SNAT_PORT));
512 	 IPACMDBG("ATTR_DNAT_PORT: 0x%x\n", nfct_get_attr_u16(ct, ATTR_DNAT_PORT));
513 
514 	 IPACMDBG("ATTR_MARK: 0x%x\n", nfct_get_attr_u32(ct, ATTR_MARK));
515 	 IPACMDBG("ATTR_USE: 0x%x\n", nfct_get_attr_u32(ct, ATTR_USE));
516 	 IPACMDBG("ATTR_ID: 0x%x\n", nfct_get_attr_u32(ct, ATTR_ID));
517 
518 	 status = nfct_get_attr_u32(ct, ATTR_STATUS);
519 	 IPACMDBG("ATTR_STATUS: 0x%x\n", status);
520 
521 	 timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT);
522 	 IPACMDBG("ATTR_TIMEOUT: 0x%x\n", timeout);
523 
524 	 if(IPS_SRC_NAT & status)
525 	 {
526 			IPACMDBG("IPS_SRC_NAT set\n");
527 	 }
528 
529 	 if(IPS_DST_NAT & status)
530 	 {
531 			IPACMDBG("IPS_DST_NAT set\n");
532 	 }
533 
534 	 if(IPS_SRC_NAT_DONE & status)
535 	 {
536 			IPACMDBG("IPS_SRC_NAT_DONE set\n");
537 	 }
538 
539 	 if(IPS_DST_NAT_DONE & status)
540 	 {
541 			IPACMDBG(" IPS_DST_NAT_DONE set\n");
542 	 }
543 
544 	 IPACMDBG("\n");
545 	 return;
546 }
547 
ParseCTV6Message(struct nf_conntrack * ct)548 void ParseCTV6Message(struct nf_conntrack *ct)
549 {
550 	 uint32_t status, timeout;
551 	 struct nfct_attr_grp_ipv6 orig_params;
552 	 uint8_t l4proto, tcp_flags, tcp_state;
553 
554 	 IPACMDBG("Printing conntrack parameters\n");
555 
556 	 nfct_get_attr_grp(ct, ATTR_GRP_ORIG_IPV6, (void *)&orig_params);
557 	 IPACMDBG("Orig src_v6_addr: 0x%08x%08x%08x%08x\n", orig_params.src[0], orig_params.src[1],
558                 	orig_params.src[2], orig_params.src[3]);
559 	IPACMDBG("Orig dst_v6_addr: 0x%08x%08x%08x%08x\n", orig_params.dst[0], orig_params.dst[1],
560                 	orig_params.dst[2], orig_params.dst[3]);
561 
562 	 IPACMDBG("ATTR_PORT_SRC = ATTR_ORIG_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC));
563 	 IPACMDBG("ATTR_PORT_DST = ATTR_ORIG_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST));
564 
565 	 IPACMDBG("ATTR_MARK: 0x%x\n", nfct_get_attr_u32(ct, ATTR_MARK));
566 	 IPACMDBG("ATTR_USE: 0x%x\n", nfct_get_attr_u32(ct, ATTR_USE));
567 	 IPACMDBG("ATTR_ID: 0x%x\n", nfct_get_attr_u32(ct, ATTR_ID));
568 
569 	 timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT);
570 	 IPACMDBG("ATTR_TIMEOUT: 0x%x\n", timeout);
571 
572 	 status = nfct_get_attr_u32(ct, ATTR_STATUS);
573 	 IPACMDBG("ATTR_STATUS: 0x%x\n", status);
574 
575 	 l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO);
576 	 IPACMDBG("ATTR_ORIG_L4PROTO: 0x%x\n", l4proto);
577 	 if(l4proto == IPPROTO_TCP)
578 	 {
579 		tcp_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE);
580 		IPACMDBG("ATTR_TCP_STATE: 0x%x\n", tcp_state);
581 
582 		tcp_flags =  nfct_get_attr_u8(ct, ATTR_TCP_FLAGS_ORIG);
583 		IPACMDBG("ATTR_TCP_FLAGS_ORIG: 0x%x\n", tcp_flags);
584 	 }
585 
586 	 IPACMDBG("\n");
587 	 return;
588 }
589 
590 #ifdef CT_OPT
ProcessCTV6Message(void * param)591 void IPACM_ConntrackListener::ProcessCTV6Message(void *param)
592 {
593 	ipacm_ct_evt_data *evt_data = (ipacm_ct_evt_data *)param;
594 	u_int8_t l4proto = 0;
595 	uint32_t status = 0;
596 	struct nf_conntrack *ct = evt_data->ct;
597 
598 #ifdef IPACM_DEBUG
599 	 char buf[1024];
600 
601 	 /* Process message and generate ioctl call to kernel thread */
602 	 nfct_snprintf(buf, sizeof(buf), evt_data->ct,
603 								 evt_data->type, NFCT_O_PLAIN, NFCT_OF_TIME);
604 	 IPACMDBG("%s\n", buf);
605 	 IPACMDBG("\n");
606 	 ParseCTV6Message(ct);
607 #endif
608 
609 	if(p_lan2lan == NULL)
610 	{
611 		IPACMERR("Lan2Lan Instance is null\n");
612 		goto IGNORE;
613 	}
614 
615 	status = nfct_get_attr_u32(ct, ATTR_STATUS);
616 	if((IPS_DST_NAT & status) || (IPS_SRC_NAT & status))
617 	{
618 		IPACMDBG("Either Destination or Source nat flag Set\n");
619 		goto IGNORE;
620 	}
621 
622 	l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO);
623 	if(IPPROTO_UDP != l4proto && IPPROTO_TCP != l4proto)
624 	{
625 		 IPACMDBG("Received unexpected protocl %d conntrack message\n", l4proto);
626 		 goto IGNORE;
627 	}
628 
629 	IPACMDBG("Neither Destination nor Source nat flag Set\n");
630 	struct nfct_attr_grp_ipv6 orig_params;
631 	nfct_get_attr_grp(ct, ATTR_GRP_ORIG_IPV6, (void *)&orig_params);
632 
633 	ipacm_event_connection lan2lan_conn;
634 	lan2lan_conn.iptype = IPA_IP_v6;
635 	memcpy(lan2lan_conn.src_ipv6_addr, orig_params.src,
636 				 sizeof(lan2lan_conn.src_ipv6_addr));
637     IPACMDBG("Before convert, src_v6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.src_ipv6_addr[0], lan2lan_conn.src_ipv6_addr[1],
638                 	lan2lan_conn.src_ipv6_addr[2], lan2lan_conn.src_ipv6_addr[3]);
639     for(int cnt=0; cnt<4; cnt++)
640 	{
641 	   lan2lan_conn.src_ipv6_addr[cnt] = ntohl(lan2lan_conn.src_ipv6_addr[cnt]);
642 	}
643 	IPACMDBG("After convert src_v6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.src_ipv6_addr[0], lan2lan_conn.src_ipv6_addr[1],
644                 	lan2lan_conn.src_ipv6_addr[2], lan2lan_conn.src_ipv6_addr[3]);
645 
646 	memcpy(lan2lan_conn.dst_ipv6_addr, orig_params.dst,
647 				 sizeof(lan2lan_conn.dst_ipv6_addr));
648 	IPACMDBG("Before convert, dst_ipv6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.dst_ipv6_addr[0], lan2lan_conn.dst_ipv6_addr[1],
649                 	lan2lan_conn.dst_ipv6_addr[2], lan2lan_conn.dst_ipv6_addr[3]);
650     for(int cnt=0; cnt<4; cnt++)
651 	{
652 	   lan2lan_conn.dst_ipv6_addr[cnt] = ntohl(lan2lan_conn.dst_ipv6_addr[cnt]);
653 	}
654 	IPACMDBG("After convert, dst_ipv6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.dst_ipv6_addr[0], lan2lan_conn.dst_ipv6_addr[1],
655                 	lan2lan_conn.dst_ipv6_addr[2], lan2lan_conn.dst_ipv6_addr[3]);
656 
657 	if(((IPPROTO_UDP == l4proto) && (NFCT_T_NEW == evt_data->type)) ||
658 		 ((IPPROTO_TCP == l4proto) &&
659 			(nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_ESTABLISHED))
660 		 )
661 	{
662 			p_lan2lan->handle_new_connection(&lan2lan_conn);
663 	}
664 	else if((IPPROTO_UDP == l4proto && NFCT_T_DESTROY == evt_data->type) ||
665 					(IPPROTO_TCP == l4proto &&
666 					 nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_FIN_WAIT))
667 	{
668 			p_lan2lan->handle_del_connection(&lan2lan_conn);
669 	}
670 
671 IGNORE:
672 	/* Cleanup item that was allocated during the original CT callback */
673 	nfct_destroy(ct);
674 	return;
675 }
676 #endif
677 
ProcessCTMessage(void * param)678 void IPACM_ConntrackListener::ProcessCTMessage(void *param)
679 {
680 	 ipacm_ct_evt_data *evt_data = (ipacm_ct_evt_data *)param;
681 	 u_int8_t l4proto = 0;
682 	 bool cache_ct = false;
683 
684 #ifdef IPACM_DEBUG
685 	 char buf[1024];
686 	 unsigned int out_flags;
687 
688 	 /* Process message and generate ioctl call to kernel thread */
689 	 out_flags = (NFCT_OF_SHOW_LAYER3 | NFCT_OF_TIME | NFCT_OF_ID);
690 	 nfct_snprintf(buf, sizeof(buf), evt_data->ct,
691 								 evt_data->type, NFCT_O_PLAIN, out_flags);
692 	 IPACMDBG_H("%s\n", buf);
693 
694 	 ParseCTMessage(evt_data->ct);
695 #endif
696 
697 	 l4proto = nfct_get_attr_u8(evt_data->ct, ATTR_ORIG_L4PROTO);
698 	 if(IPPROTO_UDP != l4proto && IPPROTO_TCP != l4proto)
699 	 {
700 			IPACMDBG("Received unexpected protocl %d conntrack message\n", l4proto);
701 	 }
702 	 else
703 	 {
704 			cache_ct = ProcessTCPorUDPMsg(evt_data->ct, evt_data->type, l4proto);
705 	 }
706 
707 	 /* Cleanup item that was allocated during the original CT callback */
708 	 if (!cache_ct)
709 		nfct_destroy(evt_data->ct);
710 	 else
711 	 	CacheORDeleteConntrack(evt_data->ct, evt_data->type, l4proto);
712 	 return;
713 }
714 
AddIface(nat_table_entry * rule,bool * isTempEntry)715 bool IPACM_ConntrackListener::AddIface(
716    nat_table_entry *rule, bool *isTempEntry)
717 {
718 	int cnt;
719 
720 	*isTempEntry = false;
721 
722 	/* Special handling for Passthrough IP. */
723 	if (IPACM_Iface::ipacmcfg->ipacm_ip_passthrough_mode)
724 	{
725 		if (rule->private_ip == IPACM_Wan::getWANIP())
726 		{
727 			IPACMDBG("In Passthrough mode and entry matched with Wan IP (0x%x)\n",
728 				rule->private_ip);
729 			return true;
730 		}
731 	}
732 
733 	/* check whether nat iface or not */
734 	for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
735 	{
736 		if (nat_iface_ipv4_addr[cnt] != 0)
737 		{
738 			if (rule->private_ip == nat_iface_ipv4_addr[cnt] ||
739 				rule->target_ip == nat_iface_ipv4_addr[cnt])
740 			{
741 				IPACMDBG("matched nat_iface_ipv4_addr entry(%d)\n", cnt);
742 				iptodot("AddIface(): Nat entry match with ip addr",
743 						nat_iface_ipv4_addr[cnt]);
744 				return true;
745 			}
746 		}
747 	}
748 
749 	if (backhaul_mode == Q6_WAN)
750 	{
751 		/* check whether non nat iface or not, on Non Nat iface
752 		   add dummy rule by copying public ip to private ip */
753 		for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
754 		{
755 			if (nonnat_iface_ipv4_addr[cnt] != 0)
756 			{
757 				if (rule->private_ip == nonnat_iface_ipv4_addr[cnt] ||
758 					rule->target_ip == nonnat_iface_ipv4_addr[cnt])
759 				{
760 					IPACMDBG("matched non_nat_iface_ipv4_addr entry(%d)\n", cnt);
761 					iptodot("AddIface(): Non Nat entry match with ip addr",
762 							nonnat_iface_ipv4_addr[cnt]);
763 
764 					rule->private_ip = rule->public_ip;
765 					rule->private_port = rule->public_port;
766 					return true;
767 				}
768 			}
769 		}
770 		IPACMDBG_H("Not mtaching with non-nat ifaces\n");
771 	}
772 	else
773 		IPACMDBG("In STA mode, don't compare against non nat ifaces\n");
774 
775 	if(pConfig == NULL)
776 	{
777 		pConfig = IPACM_Config::GetInstance();
778 		if(pConfig == NULL)
779 		{
780 			IPACMERR("Unable to get Config instance\n");
781 			return false;
782 		}
783 	}
784 
785 	if (pConfig->isPrivateSubnet(rule->private_ip) ||
786 		pConfig->isPrivateSubnet(rule->target_ip))
787 	{
788 		IPACMDBG("Matching with Private subnet\n");
789 		*isTempEntry = true;
790 		return true;
791 	}
792 
793 	return false;
794 }
795 
AddORDeleteNatEntry(const nat_entry_bundle * input)796 void IPACM_ConntrackListener::AddORDeleteNatEntry(const nat_entry_bundle *input)
797 {
798 	u_int8_t tcp_state;
799 
800 	if (nat_inst == NULL)
801 	{
802 		IPACMERR("Nat instance is NULL, unable to add or delete\n");
803 		return;
804 	}
805 
806 	IPACMDBG_H("Below Nat Entry will either be added or deleted\n");
807 	iptodot("AddORDeleteNatEntry(): target ip or dst ip",
808 			input->rule->target_ip);
809 	IPACMDBG("target port or dst port: 0x%x Decimal:%d\n",
810 			 input->rule->target_port, input->rule->target_port);
811 	iptodot("AddORDeleteNatEntry(): private ip or src ip",
812 			input->rule->private_ip);
813 	IPACMDBG("private port or src port: 0x%x, Decimal:%d\n",
814 			 input->rule->private_port, input->rule->private_port);
815 	IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n",
816 			 input->rule->public_port, input->rule->public_port);
817 	IPACMDBG("Protocol: %d, destination nat flag: %d\n",
818 			 input->rule->protocol, input->rule->dst_nat);
819 
820 	if (IPPROTO_TCP == input->rule->protocol)
821 	{
822 		tcp_state = nfct_get_attr_u8(input->ct, ATTR_TCP_STATE);
823 		if (TCP_CONNTRACK_ESTABLISHED == tcp_state)
824 		{
825 			IPACMDBG("TCP state TCP_CONNTRACK_ESTABLISHED(%d)\n", tcp_state);
826 			if (!CtList->isWanUp())
827 			{
828 				IPACMDBG("Wan is not up, cache connections\n");
829 				nat_inst->CacheEntry(input->rule);
830 			}
831 			else if (input->isTempEntry)
832 			{
833 				nat_inst->AddTempEntry(input->rule);
834 			}
835 			else
836 			{
837 				nat_inst->AddEntry(input->rule);
838 			}
839 		}
840 		else if (TCP_CONNTRACK_FIN_WAIT == tcp_state ||
841 				   input->type == NFCT_T_DESTROY)
842 		{
843 			IPACMDBG("TCP state TCP_CONNTRACK_FIN_WAIT(%d) "
844 					 "or type NFCT_T_DESTROY(%d)\n", tcp_state, input->type);
845 
846 			nat_inst->DeleteEntry(input->rule);
847 			nat_inst->DeleteTempEntry(input->rule);
848 		}
849 		else
850 		{
851 			IPACMDBG("Ignore tcp state: %d and type: %d\n",
852 					 tcp_state, input->type);
853 		}
854 
855 	}
856 	else if (IPPROTO_UDP == input->rule->protocol)
857 	{
858 		if (NFCT_T_NEW == input->type || NFCT_T_UPDATE == input->type)
859 		{
860 			IPACMDBG("New UDP connection at time %ld\n", time(NULL));
861 			if (!CtList->isWanUp())
862 			{
863 				IPACMDBG("Wan is not up, cache connections\n");
864 				nat_inst->CacheEntry(input->rule);
865 			}
866 			else if (input->isTempEntry)
867 			{
868 				nat_inst->AddTempEntry(input->rule);
869 			}
870 			else
871 			{
872 				nat_inst->AddEntry(input->rule);
873 			}
874 		}
875 		else if (NFCT_T_DESTROY == input->type)
876 		{
877 			IPACMDBG("UDP connection close at time %ld\n", time(NULL));
878 			nat_inst->DeleteEntry(input->rule);
879 			nat_inst->DeleteTempEntry(input->rule);
880 		}
881 	}
882 
883 	return;
884 }
885 
PopulateTCPorUDPEntry(struct nf_conntrack * ct,uint32_t status,nat_table_entry * rule)886 void IPACM_ConntrackListener::PopulateTCPorUDPEntry(
887 	 struct nf_conntrack *ct,
888 	 uint32_t status,
889 	 nat_table_entry *rule)
890 {
891 	uint32_t repl_dst_ip;
892 
893 	if (IPS_DST_NAT == status)
894 	{
895 		IPACMDBG("Destination NAT\n");
896 		rule->dst_nat = true;
897 
898 		IPACMDBG("Parse reply tuple\n");
899 		rule->target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
900 		rule->target_ip = ntohl(rule->target_ip);
901 		iptodot("PopulateTCPorUDPEntry(): target ip", rule->target_ip);
902 
903 		/* Retriev target/dst port */
904 		rule->target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
905 		rule->target_port = ntohs(rule->target_port);
906 		if (0 == rule->target_port)
907 		{
908 			IPACMDBG("unable to retrieve target port\n");
909 		}
910 
911 		rule->public_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
912 		rule->public_port = ntohs(rule->public_port);
913 
914 		/* Retriev src/private ip address */
915 		rule->private_ip = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC);
916 		rule->private_ip = ntohl(rule->private_ip);
917 		iptodot("PopulateTCPorUDPEntry(): private ip", rule->private_ip);
918 		if (0 == rule->private_ip)
919 		{
920 			IPACMDBG("unable to retrieve private ip address\n");
921 		}
922 
923 		/* Retriev src/private port */
924 		rule->private_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC);
925 		rule->private_port = ntohs(rule->private_port);
926 		if (0 == rule->private_port)
927 		{
928 			IPACMDBG("unable to retrieve private port\n");
929 		}
930 	}
931 	else if (IPS_SRC_NAT == status)
932 	{
933 		IPACMDBG("Source NAT\n");
934 		rule->dst_nat = false;
935 
936 		/* Retriev target/dst ip address */
937 		IPACMDBG("Parse source tuple\n");
938 		rule->target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST);
939 		rule->target_ip = ntohl(rule->target_ip);
940 		iptodot("PopulateTCPorUDPEntry(): target ip", rule->target_ip);
941 		if (0 == rule->target_ip)
942 		{
943 			IPACMDBG("unable to retrieve target ip address\n");
944 		}
945 		/* Retriev target/dst port */
946 		rule->target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
947 		rule->target_port = ntohs(rule->target_port);
948 		if (0 == rule->target_port)
949 		{
950 			IPACMDBG("unable to retrieve target port\n");
951 		}
952 
953 		/* Retriev public port */
954 		rule->public_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST);
955 		rule->public_port = ntohs(rule->public_port);
956 		if (0 == rule->public_port)
957 		{
958 			IPACMDBG("unable to retrieve public port\n");
959 		}
960 
961 		/* Retriev src/private ip address */
962 		rule->private_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
963 		rule->private_ip = ntohl(rule->private_ip);
964 		iptodot("PopulateTCPorUDPEntry(): private ip", rule->private_ip);
965 		if (0 == rule->private_ip)
966 		{
967 			IPACMDBG("unable to retrieve private ip address\n");
968 		}
969 
970 		/* Retriev src/private port */
971 		rule->private_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
972 		rule->private_port = ntohs(rule->private_port);
973 		if (0 == rule->private_port)
974 		{
975 			IPACMDBG("unable to retrieve private port\n");
976 		}
977 
978 		/* If Reply destination IP is not Public IP, install dummy NAT rule. */
979 		repl_dst_ip = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST);
980 		repl_dst_ip = ntohl(repl_dst_ip);
981 		if(repl_dst_ip != rule->public_ip)
982 		{
983 			IPACMDBG_H("Reply dst IP:0x%x not equal to wan ip:0x%x\n",repl_dst_ip, rule->public_ip);
984 			rule->private_ip = rule->public_ip;
985 		}
986 	}
987 
988 	return;
989 }
990 
991 #ifdef CT_OPT
HandleLan2Lan(struct nf_conntrack * ct,enum nf_conntrack_msg_type type,nat_table_entry * rule)992 void IPACM_ConntrackListener::HandleLan2Lan(struct nf_conntrack *ct,
993 	enum nf_conntrack_msg_type type,
994 	 nat_table_entry *rule)
995 {
996 	ipacm_event_connection lan2lan_conn = { 0 };
997 
998 	if (p_lan2lan == NULL)
999 	{
1000 		IPACMERR("Lan2Lan Instance is null\n");
1001 		return;
1002 	}
1003 
1004 	lan2lan_conn.iptype = IPA_IP_v4;
1005 	lan2lan_conn.src_ipv4_addr = orig_src_ip;
1006 	lan2lan_conn.dst_ipv4_addr = orig_dst_ip;
1007 
1008 	if (((IPPROTO_UDP == rule->protocol) && (NFCT_T_NEW == type)) ||
1009 		((IPPROTO_TCP == rule->protocol) && (nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_ESTABLISHED)))
1010 	{
1011 		p_lan2lan->handle_new_connection(&lan2lan_conn);
1012 	}
1013 	else if ((IPPROTO_UDP == rule->protocol && NFCT_T_DESTROY == type) ||
1014 			   (IPPROTO_TCP == rule->protocol &&
1015 				nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_FIN_WAIT))
1016 	{
1017 		p_lan2lan->handle_del_connection(&lan2lan_conn);
1018 	}
1019 }
1020 #endif
1021 
CheckSTAClient(const nat_table_entry * rule,bool * isTempEntry)1022 void IPACM_ConntrackListener::CheckSTAClient(
1023    const nat_table_entry *rule, bool *isTempEntry)
1024 {
1025 	int nCnt;
1026 
1027 	/* Check whether target is in STA client list or not
1028       if not ignore the connection */
1029 	 if((backhaul_mode == Q6_WAN) || (StaClntCnt == 0))
1030 	 {
1031 		return;
1032 	 }
1033 
1034 	 if((sta_clnt_ipv4_addr[0] & STA_CLNT_SUBNET_MASK) !=
1035 		 (rule->target_ip & STA_CLNT_SUBNET_MASK))
1036 	 {
1037 		IPACMDBG("STA client subnet mask not matching\n");
1038 		return;
1039 	 }
1040 
1041 	 IPACMDBG("StaClntCnt %d\n", StaClntCnt);
1042 	 for(nCnt = 0; nCnt < StaClntCnt; nCnt++)
1043 	 {
1044 		IPACMDBG("Comparing trgt_ip 0x%x with sta clnt ip: 0x%x\n",
1045 			 rule->target_ip, sta_clnt_ipv4_addr[nCnt]);
1046 		if(rule->target_ip == sta_clnt_ipv4_addr[nCnt])
1047 		{
1048 			IPACMDBG("Match index %d\n", nCnt);
1049 			return;
1050 		}
1051 	 }
1052 
1053 	IPACMDBG_H("Not matching with STA Clnt Ip Addrs 0x%x\n",
1054 		rule->target_ip);
1055 	*isTempEntry = true;
1056 }
1057 
1058 /* conntrack send in host order and ipa expects in host order */
ProcessTCPorUDPMsg(struct nf_conntrack * ct,enum nf_conntrack_msg_type type,u_int8_t l4proto)1059 bool IPACM_ConntrackListener::ProcessTCPorUDPMsg(
1060 	 struct nf_conntrack *ct,
1061 	 enum nf_conntrack_msg_type type,
1062 	 u_int8_t l4proto)
1063 {
1064 	 nat_table_entry rule;
1065 	 uint32_t status = 0;
1066 	 uint32_t orig_src_ip, orig_dst_ip;
1067 	 bool isAdd = false;
1068 	 bool cache_ct = false;
1069 
1070 	 nat_entry_bundle nat_entry;
1071 	 nat_entry.isTempEntry = false;
1072 	 nat_entry.ct = ct;
1073 	 nat_entry.type = type;
1074 
1075 	memset(&rule, 0, sizeof(rule));
1076 	IPACMDBG("Received type:%d with proto:%d\n", type, l4proto);
1077 	status = nfct_get_attr_u32(ct, ATTR_STATUS);
1078 
1079 	 /* Retrieve Protocol */
1080 	 rule.protocol = nfct_get_attr_u8(ct, ATTR_REPL_L4PROTO);
1081 
1082 	 if(IPS_DST_NAT & status)
1083 	 {
1084 		 status = IPS_DST_NAT;
1085 	 }
1086 	 else if(IPS_SRC_NAT & status)
1087 	 {
1088 		 status = IPS_SRC_NAT;
1089 	 }
1090 	 else
1091 	 {
1092 		 IPACMDBG("Neither Destination nor Source nat flag Set\n");
1093 		 orig_src_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
1094 		 orig_src_ip = ntohl(orig_src_ip);
1095 		 if(orig_src_ip == 0)
1096 		 {
1097 			 IPACMERR("unable to retrieve orig src ip address\n");
1098 			 return cache_ct;
1099 		 }
1100 
1101 		 orig_dst_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST);
1102 		 orig_dst_ip = ntohl(orig_dst_ip);
1103 		 if(orig_dst_ip == 0)
1104 		 {
1105 			 IPACMERR("unable to retrieve orig dst ip address\n");
1106 			 return cache_ct;
1107 		 }
1108 
1109 		if(orig_src_ip == wan_ipaddr)
1110 		{
1111 			IPACMDBG("orig src ip:0x%x equal to wan ip\n",orig_src_ip);
1112 			status = IPS_SRC_NAT;
1113 		}
1114 		else if(orig_dst_ip == wan_ipaddr)
1115 		{
1116 			IPACMDBG("orig Dst IP:0x%x equal to wan ip\n",orig_dst_ip);
1117 			status = IPS_DST_NAT;
1118 		}
1119 		else
1120 		{
1121 			IPACMDBG_H("Neither orig src ip:0x%x Nor orig Dst IP:0x%x equal to wan ip:0x%x\n",
1122 					   orig_src_ip, orig_dst_ip, wan_ipaddr);
1123 
1124 #ifdef CT_OPT
1125 			HandleLan2Lan(ct, type, &rule);
1126 #endif
1127 		 	IPACMDBG("Neither source Nor destination nat.\n");
1128 			/* If WAN is not up, cache the event. */
1129 			if(!CtList->isWanUp())
1130 				cache_ct = true;
1131 			goto IGNORE;
1132 		}
1133 	}
1134 
1135 	rule.public_ip = wan_ipaddr;
1136 	PopulateTCPorUDPEntry(ct, status, &rule);
1137 
1138 	if (rule.private_ip != wan_ipaddr)
1139 	{
1140 		isAdd = AddIface(&rule, &nat_entry.isTempEntry);
1141 		if (!isAdd)
1142 		{
1143 			goto IGNORE;
1144 		}
1145 	}
1146 	else
1147 	{
1148 		if (backhaul_mode != Q6_WAN)
1149 		{
1150 			IPACMDBG("In STA mode, ignore connections destinated to STA interface\n");
1151 			goto IGNORE;
1152 		}
1153 
1154 		IPACMDBG("For embedded connections add dummy nat rule\n");
1155 		IPACMDBG("Change private port %d to %d\n",
1156 				rule.private_port, rule.public_port);
1157 		rule.private_port = rule.public_port;
1158 	}
1159 
1160 	CheckSTAClient(&rule, &nat_entry.isTempEntry);
1161 	nat_entry.rule = &rule;
1162 	AddORDeleteNatEntry(&nat_entry);
1163 	return cache_ct;
1164 
1165 IGNORE:
1166 	IPACMDBG_H("ignoring below Nat Entry\n");
1167 	iptodot("ProcessTCPorUDPMsg(): target ip or dst ip", rule.target_ip);
1168 	IPACMDBG("target port or dst port: 0x%x Decimal:%d\n", rule.target_port, rule.target_port);
1169 	iptodot("ProcessTCPorUDPMsg(): private ip or src ip", rule.private_ip);
1170 	IPACMDBG("private port or src port: 0x%x, Decimal:%d\n", rule.private_port, rule.private_port);
1171 	IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n", rule.public_port, rule.public_port);
1172 	IPACMDBG("Protocol: %d, destination nat flag: %d\n", rule.protocol, rule.dst_nat);
1173 	return cache_ct;
1174 }
1175 
HandleSTAClientAddEvt(uint32_t clnt_ip_addr)1176 void IPACM_ConntrackListener::HandleSTAClientAddEvt(uint32_t clnt_ip_addr)
1177 {
1178 	 int cnt;
1179 	 IPACMDBG_H("Received STA client 0x%x\n", clnt_ip_addr);
1180 
1181 	 if(StaClntCnt >= MAX_STA_CLNT_IFACES)
1182 	 {
1183 		IPACMDBG("Max STA client reached, ignore 0x%x\n", clnt_ip_addr);
1184 		return;
1185 	 }
1186 
1187 	 for(cnt=0; cnt<MAX_STA_CLNT_IFACES; cnt++)
1188 	 {
1189 		if(sta_clnt_ipv4_addr[cnt] != 0 &&
1190 		 sta_clnt_ipv4_addr[cnt] == clnt_ip_addr)
1191 		{
1192 			IPACMDBG("Ignoring duplicate one 0x%x\n", clnt_ip_addr);
1193 			break;
1194 		}
1195 
1196 		if(sta_clnt_ipv4_addr[cnt] == 0)
1197 		{
1198 			IPACMDBG("Adding STA client 0x%x at Index: %d\n",
1199 					clnt_ip_addr, cnt);
1200 			sta_clnt_ipv4_addr[cnt] = clnt_ip_addr;
1201 			StaClntCnt++;
1202 			IPACMDBG("STA client cnt %d\n", StaClntCnt);
1203 			break;
1204 		}
1205 
1206 	 }
1207 
1208 	 nat_inst->FlushTempEntries(clnt_ip_addr, true);
1209 	 return;
1210 }
1211 
HandleSTAClientDelEvt(uint32_t clnt_ip_addr)1212 void IPACM_ConntrackListener::HandleSTAClientDelEvt(uint32_t clnt_ip_addr)
1213 {
1214 	 int cnt;
1215 	 IPACMDBG_H("Received STA client 0x%x\n", clnt_ip_addr);
1216 
1217 	 for(cnt=0; cnt<MAX_STA_CLNT_IFACES; cnt++)
1218 	 {
1219 		if(sta_clnt_ipv4_addr[cnt] != 0 &&
1220 		 sta_clnt_ipv4_addr[cnt] == clnt_ip_addr)
1221 		{
1222 			IPACMDBG("Deleting STA client 0x%x at index: %d\n",
1223 					clnt_ip_addr, cnt);
1224 			sta_clnt_ipv4_addr[cnt] = 0;
1225 			nat_inst->DelEntriesOnSTAClntDiscon(clnt_ip_addr);
1226 			StaClntCnt--;
1227 			IPACMDBG("STA client cnt %d\n", StaClntCnt);
1228 			break;
1229 		}
1230 	 }
1231 
1232 	 nat_inst->FlushTempEntries(clnt_ip_addr, false);
1233    return;
1234 }
1235 
isLocalHostAddr(uint32_t src_ip_addr,uint32_t dst_ip_addr)1236 bool isLocalHostAddr(uint32_t src_ip_addr, uint32_t dst_ip_addr) {
1237 
1238 	src_ip_addr = ntohl(src_ip_addr);
1239 	dst_ip_addr = ntohl(dst_ip_addr);
1240 	if ((src_ip_addr & LOOPBACK_MASK) == LOOPBACK_ADDR || (dst_ip_addr & LOOPBACK_MASK) == LOOPBACK_ADDR) /* (loopback) */
1241 		return true;
1242 	return false;
1243 }
1244 
readConntrack(int fd)1245 void IPACM_ConntrackListener::readConntrack(int fd) {
1246 
1247 	int recv_bytes = -1, index = 0, len =0;
1248 	char buffer[CT_ENTRIES_BUFFER_SIZE];
1249 	struct nf_conntrack *ct;
1250 	struct nlmsghdr *nl_header;
1251    	struct iovec iov = {
1252 		.iov_base	= buffer,
1253 		.iov_len	= CT_ENTRIES_BUFFER_SIZE,
1254 	};
1255 	struct sockaddr_nl addr;
1256 	struct msghdr msg = {
1257 		.msg_name	= &addr,
1258 		.msg_namelen	= sizeof(struct sockaddr_nl),
1259 		.msg_iov	= &iov,
1260 		.msg_iovlen	= 1,
1261 		.msg_control	= NULL,
1262 		.msg_controllen	= 0,
1263 		.msg_flags	= 0,
1264 	};
1265 
1266 	len = MAX_CONNTRACK_ENTRIES * sizeof(ct_entry);
1267 
1268 	ct_entries = (ct_entry *) malloc(len);
1269 	if(ct_entries == NULL)
1270 	{
1271 		IPACMERR("unable to allocate ct_entries memory \n");
1272 		return;
1273 	}
1274 	memset(ct_entries, 0, len);
1275 
1276 	if( fd < 0)
1277 	{
1278 		IPACMDBG_H("Invalid fd %d \n",fd);
1279 		free(ct_entries);
1280 		return;
1281 	}
1282 	IPACMDBG_H("receiving conntrack entries started.\n");
1283 	len = CT_ENTRIES_BUFFER_SIZE;
1284 	while (len > 0)
1285 	{
1286 		memset(buffer, 0, CT_ENTRIES_BUFFER_SIZE);
1287 		recv_bytes = recvmsg(fd, &msg, 0);
1288 		if(recv_bytes < 0)
1289 		{
1290 			IPACMDBG_H("error in receiving conntrack entries %d%s\n",errno, strerror(errno));
1291 			break;
1292 		}
1293 		else
1294 		{
1295 			len -= recv_bytes;
1296 			nl_header = (struct nlmsghdr *)buffer;
1297 			IPACMDBG_H("Number of bytes:%d to parse\n", recv_bytes);
1298 			while(NLMSG_OK(nl_header, recv_bytes) && (index < MAX_CONNTRACK_ENTRIES))
1299 			{
1300 				if (nl_header->nlmsg_type == NLMSG_ERROR)
1301 				{
1302 					IPACMDBG_H("Error, recv_bytes is %d\n",recv_bytes);
1303 					break;
1304 				}
1305 				ct = nfct_new();
1306 				if (ct != NULL)
1307 				{
1308 					int parseResult =  nfct_parse_conntrack((nf_conntrack_msg_type) NFCT_T_ALL,nl_header, ct);
1309 					if(parseResult != NFCT_T_ERROR && parseResult != 0)
1310 					{
1311 						ct_entries[index].ct = ct;
1312 						ct_entries[index++].type = (nf_conntrack_msg_type)parseResult;
1313 					}
1314 					else
1315 					{
1316 						IPACMDBG_H("error in parsing  %d%s \n", errno, strerror(errno));
1317 						nfct_destroy(ct);
1318 					}
1319 				}
1320 				else
1321 				{
1322 					IPACMDBG_H("ct allocation failed\n");
1323 				}
1324 				if (nl_header->nlmsg_type == NLMSG_DONE)
1325 				{
1326 					IPACMDBG_H("Message is done.\n");
1327 					break;
1328 				}
1329 				nl_header = NLMSG_NEXT(nl_header, recv_bytes);
1330 			}
1331 		}
1332 	}
1333 
1334 	isReadCTDone = true;
1335 	IPACMDBG_H("receiving conntrack entries ended. No of entries: %d\n", index);
1336 	if(isWanUp() && !isProcessCTDone)
1337 	{
1338 		IPACMDBG_H("wan is up, process ct entries \n");
1339 		processConntrack();
1340 	}
1341 
1342 	return ;
1343 }
1344 
processConntrack()1345 void IPACM_ConntrackListener::processConntrack() {
1346 
1347 	uint8_t ip_type;
1348 	int index = 0;
1349 	ipacm_ct_evt_data *ct_data;
1350 	IPACMDBG_H("process conntrack started \n");
1351 	if(ct_entries != NULL)
1352 	{
1353 		while(ct_entries[index].ct != NULL)
1354 		{
1355 			ip_type = nfct_get_attr_u8(ct_entries[index].ct, ATTR_REPL_L3PROTO);
1356 			if((AF_INET == ip_type) && isLocalHostAddr(nfct_get_attr_u32(ct_entries[index].ct, ATTR_ORIG_IPV4_SRC),
1357 					nfct_get_attr_u32(ct_entries[index].ct, ATTR_ORIG_IPV4_DST)))
1358 			{
1359 				IPACMDBG_H(" loopback entry \n");
1360 				goto IGNORE;
1361 			}
1362 
1363 #ifndef CT_OPT
1364 			if(AF_INET6 == ip_type)
1365 			{
1366 				IPACMDBG("Ignoring ipv6(%d) connections\n", ip_type);
1367 				goto IGNORE;
1368 			}
1369 #endif
1370 
1371 			ct_data = (ipacm_ct_evt_data *)malloc(sizeof(ipacm_ct_evt_data));
1372 			if(ct_data == NULL)
1373 			{
1374 				IPACMERR("unable to allocate memory \n");
1375 				goto IGNORE;
1376 			}
1377 
1378 			ct_data->ct = ct_entries[index].ct;
1379 			ct_data->type = ct_entries[index].type;
1380 
1381 #ifdef CT_OPT
1382 			if(AF_INET6 == ip_type)
1383 			{
1384 				ProcessCTV6Message(ct_data);
1385 			}
1386 #else
1387 				ProcessCTMessage(ct_data);
1388 #endif
1389 		index++;
1390 		free(ct_data);
1391 		continue;
1392 IGNORE:
1393 		nfct_destroy(ct_entries[index].ct);
1394 		index++;
1395 		}
1396 	}
1397 	else
1398 	{
1399 		IPACMDBG_H("ct entry is null\n");
1400 		return ;
1401 	}
1402 	isProcessCTDone = true;
1403 	free(ct_entries);
1404 	ct_entries = NULL;
1405 	IPACMDBG_H("process conntrack ended. Number of entries:%d \n", index);
1406 	return;
1407 }
1408 
CacheORDeleteConntrack(struct nf_conntrack * ct,enum nf_conntrack_msg_type type,u_int8_t protocol)1409 void IPACM_ConntrackListener::CacheORDeleteConntrack
1410 (
1411 	struct nf_conntrack *ct,
1412 	enum nf_conntrack_msg_type type,
1413 	u_int8_t protocol
1414 )
1415 {
1416 	u_int8_t tcp_state;
1417 	int i = 0, free_idx = -1;
1418 
1419 	IPACMDBG("CT entry, type (%d), protocol(%d)\n", type, protocol);
1420 	/* Check for duplicate entry and in parallel find first free index. */
1421 	for(; i < MAX_CONNTRACK_ENTRIES; i++)
1422 	{
1423 		if (ct_cache[i].ct != NULL)
1424 		{
1425 			if (nfct_cmp(ct_cache[i].ct, ct, NFCT_CMP_ORIG | NFCT_CMP_REPL))
1426 			{
1427 				/* Duplicate entry. */
1428 				IPACMDBG("Duplicate CT entry, type (%d), protocol(%d)\n",
1429 					type, protocol);
1430 				break;
1431 			}
1432 		}
1433 		else if ((ct_cache[i].ct == NULL) && (free_idx == -1))
1434 		{
1435 			/* Cache the first free index. */
1436 			free_idx = i;
1437 		}
1438 	}
1439 
1440 	/* Duplicate entry handling. */
1441 	if (i < MAX_CONNTRACK_ENTRIES)
1442 	{
1443 		if (IPPROTO_TCP == protocol)
1444 		{
1445 			tcp_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE);
1446 			if (TCP_CONNTRACK_FIN_WAIT == tcp_state || type == NFCT_T_DESTROY)
1447 			{
1448 				IPACMDBG("TCP state TCP_CONNTRACK_FIN_WAIT(%d) "
1449 							 "or type NFCT_T_DESTROY\n", tcp_state);
1450 				nfct_destroy(ct_cache[i].ct);
1451 				nfct_destroy(ct);
1452 				memset(&ct_cache[i], 0, sizeof(ct_cache[i]));
1453 				return ;
1454 			}
1455 		}
1456 		if ((IPPROTO_UDP == protocol) && (type == NFCT_T_DESTROY))
1457 		{
1458 			IPACMDBG("UDP type NFCT_T_DESTROY\n");
1459 			nfct_destroy(ct_cache[i].ct);
1460 			nfct_destroy(ct);
1461 			memset(&ct_cache[i], 0, sizeof(ct_cache[i]));
1462 			return;
1463 		}
1464 	}
1465 	else if ((i == MAX_CONNTRACK_ENTRIES) &&
1466 		(type != NFCT_T_DESTROY) && (free_idx != -1))
1467 	{
1468 		if (IPPROTO_TCP == protocol)
1469 		{
1470 			tcp_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE);
1471 			if (TCP_CONNTRACK_ESTABLISHED == tcp_state)
1472 			{
1473 				IPACMDBG("TCP state TCP_CONNTRACK_ESTABLISHED\n");
1474 				/* Cache the entry. */
1475 				ct_cache[free_idx].ct = ct;
1476 				ct_cache[free_idx].protocol = protocol;
1477 				ct_cache[free_idx].type = type;
1478 				return;
1479 			}
1480 		}
1481 		if (IPPROTO_UDP == protocol)
1482 		{
1483 			if (NFCT_T_NEW  == type)
1484 			{
1485 				IPACMDBG("New UDP connection\n");
1486 				/* Cache the entry. */
1487 				ct_cache[free_idx].ct = ct;
1488 				ct_cache[free_idx].protocol = protocol;
1489 				ct_cache[free_idx].type = type;
1490 				return;
1491 			}
1492 		}
1493 	}
1494 	/* In all other cases, free the conntracy entry. */
1495 	nfct_destroy(ct);
1496 	return ;
1497 }
processCacheConntrack(void)1498 void IPACM_ConntrackListener::processCacheConntrack(void)
1499 {
1500 	int i = 0;
1501 
1502 	IPACMDBG("Entry:\n");
1503 	for(; i < MAX_CONNTRACK_ENTRIES; i++)
1504 	{
1505 		if (ct_cache[i].ct != NULL)
1506 		{
1507 			ProcessTCPorUDPMsg(ct_cache[i].ct, ct_cache[i].type, ct_cache[i].protocol);
1508 			nfct_destroy(ct_cache[i].ct);
1509 			memset(&ct_cache[i], 0, sizeof(ct_cache[i]));
1510 		}
1511 	}
1512 	IPACMDBG("Exit:\n");
1513 }
1514 
1515