1 /*
2 Copyright (c) 2013-2018, 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 <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <arpa/inet.h>
35 #include <netinet/in.h>
36 #include <sys/ioctl.h>
37 #include <net/if.h>
38 #include "IPACM_Iface.h"
39 #include "IPACM_ConntrackListener.h"
40 #include "IPACM_ConntrackClient.h"
41 #include "IPACM_Log.h"
42 
43 #define LO_NAME "lo"
44 
45 extern IPACM_EvtDispatcher cm_dis;
46 extern void ParseCTMessage(struct nf_conntrack *ct);
47 
48 IPACM_ConntrackClient *IPACM_ConntrackClient::pInstance = NULL;
49 IPACM_ConntrackListener *CtList = NULL;
50 
51 /* ================================
52 		 Local Function Definitions
53 		 =================================
54 */
IPACM_ConntrackClient()55 IPACM_ConntrackClient::IPACM_ConntrackClient()
56 {
57 	IPACMDBG("\n");
58 
59 	tcp_hdl = NULL;
60 	udp_hdl = NULL;
61 	tcp_filter = NULL;
62 	udp_filter = NULL;
63 	fd_tcp = -1;
64 	fd_udp = -1;
65 	subscrips_tcp = NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY;
66 	subscrips_udp = NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY;
67 }
68 
GetInstance()69 IPACM_ConntrackClient* IPACM_ConntrackClient::GetInstance()
70 {
71 	if(pInstance == NULL)
72 	{
73 		pInstance = new IPACM_ConntrackClient();
74 
75 		pInstance->udp_filter = nfct_filter_create();
76 		if(pInstance->udp_filter == NULL)
77 		{
78 			IPACMERR("unable to create UDP filter\n");
79 			delete pInstance;
80 			return NULL;
81 		}
82 		IPACMDBG("Created UDP filter\n");
83 
84 		pInstance->tcp_filter = nfct_filter_create();
85 		if(pInstance->tcp_filter == NULL)
86 		{
87 			IPACMERR("unable to create TCP filter\n");
88 			delete pInstance;
89 			return NULL;
90 		}
91 		IPACMDBG("Created TCP filter\n");
92 	}
93 
94 	return pInstance;
95 }
96 
IPAConntrackEventCB(enum nf_conntrack_msg_type type,struct nf_conntrack * ct,void * data)97 int IPACM_ConntrackClient::IPAConntrackEventCB
98 (
99 	 enum nf_conntrack_msg_type type,
100 	 struct nf_conntrack *ct,
101 	 void *data
102 	 )
103 {
104 	ipacm_cmd_q_data evt_data;
105 	ipacm_ct_evt_data *ct_data;
106 	uint8_t ip_type = 0;
107 	data = NULL;
108 
109 	IPACMDBG("Event callback called with msgtype: %d\n",type);
110 
111 	/* Retrieve ip type */
112 	ip_type = nfct_get_attr_u8(ct, ATTR_REPL_L3PROTO);
113 
114 #ifndef CT_OPT
115 	if(AF_INET6 == ip_type)
116 	{
117 		IPACMDBG("Ignoring ipv6(%d) connections\n", ip_type);
118 		goto IGNORE;
119 	}
120 
121 #endif
122 
123 	ct_data = (ipacm_ct_evt_data *)malloc(sizeof(ipacm_ct_evt_data));
124 	if(ct_data == NULL)
125 	{
126 		IPACMERR("unable to allocate memory \n");
127 		goto IGNORE;
128 	}
129 
130 	ct_data->ct = ct;
131 	ct_data->type = type;
132 
133 	evt_data.event = IPA_PROCESS_CT_MESSAGE;
134 	evt_data.evt_data = (void *)ct_data;
135 
136 #ifdef CT_OPT
137 	if(AF_INET6 == ip_type)
138 	{
139 		evt_data.event = IPA_PROCESS_CT_MESSAGE_V6;
140 	}
141 #endif
142 
143 	if(0 != IPACM_EvtDispatcher::PostEvt(&evt_data))
144 	{
145 		IPACMERR("Error sending Conntrack message to processing thread!\n");
146 		free(ct_data);
147 		goto IGNORE;
148 	}
149 
150 /* NFCT_CB_STOLEN means that the conntrack object is not released after the
151 	 callback That must be manually done later when the object is no longer needed. */
152 	return NFCT_CB_STOLEN;
153 
154 IGNORE:
155 	nfct_destroy(ct);
156 	return NFCT_CB_STOLEN;
157 
158 }
159 
IPA_Conntrack_Filters_Ignore_Bridge_Addrs(struct nfct_filter * filter)160 int IPACM_ConntrackClient::IPA_Conntrack_Filters_Ignore_Bridge_Addrs
161 (
162 	 struct nfct_filter *filter
163 )
164 {
165 	int fd;
166 	fd = socket(AF_INET, SOCK_DGRAM, 0);
167 	if(fd < 0)
168 	{
169 		PERROR("unable to open socket");
170 		return -1;
171 	}
172 
173 	int ret;
174 	uint32_t ipv4_addr;
175 	struct ifreq ifr;
176 
177 	/* retrieve bridge interface ipv4 address */
178 	memset(&ifr, 0, sizeof(struct ifreq));
179 	ifr.ifr_addr.sa_family = AF_INET;
180 
181 	if(strlen(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name) >= sizeof(ifr.ifr_name))
182 	{
183 		IPACMERR("interface name overflows: len %zu\n",
184 			strlen(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name));
185 		close(fd);
186 		return -1;
187 	}
188 	(void)strlcpy(ifr.ifr_name, IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, sizeof(ifr.ifr_name));
189 	IPACMDBG("bridge interface name (%s)\n", ifr.ifr_name);
190 
191 	ret = ioctl(fd, SIOCGIFADDR, &ifr);
192 	if (ret < 0)
193 	{
194 		IPACMERR("unable to retrieve (%s) interface address\n",ifr.ifr_name);
195 		close(fd);
196 		return -1;
197 	}
198 	IPACMDBG("Interface (%s) address %s\n", ifr.ifr_name, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
199 	ipv4_addr = ntohl(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr);
200 	close(fd);
201 
202 	/* ignore whatever is destined to or originates from broadcast ip address */
203 	struct nfct_filter_ipv4 filter_ipv4;
204 
205 	filter_ipv4.addr = ipv4_addr;
206 	filter_ipv4.mask = 0xffffffff;
207 
208 	nfct_filter_set_logic(filter,
209 												NFCT_FILTER_DST_IPV4,
210 												NFCT_FILTER_LOGIC_NEGATIVE);
211 
212 	nfct_filter_add_attr(filter, NFCT_FILTER_DST_IPV4, &filter_ipv4);
213 
214 	nfct_filter_set_logic(filter,
215 												NFCT_FILTER_SRC_IPV4,
216 												NFCT_FILTER_LOGIC_NEGATIVE);
217 
218 	nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4);
219 
220 	return 0;
221 }
222 
IPA_Conntrack_Filters_Ignore_Local_Iface(struct nfct_filter * filter,ipacm_event_iface_up * param)223 int IPACM_ConntrackClient::IPA_Conntrack_Filters_Ignore_Local_Iface
224 (
225 	 struct nfct_filter *filter,
226 	 ipacm_event_iface_up *param
227 )
228 {
229 	struct nfct_filter_ipv4 filter_ipv4;
230 
231 	filter_ipv4.addr = param->ipv4_addr;
232 	filter_ipv4.mask = 0xffffffff;
233 
234 	/* ignore whatever is destined to local interfaces */
235 	IPACMDBG("Ignore connections destinated to interface %s", param->ifname);
236 	iptodot("with ipv4 address", param->ipv4_addr);
237 	nfct_filter_set_logic(filter,
238 												NFCT_FILTER_DST_IPV4,
239 												NFCT_FILTER_LOGIC_NEGATIVE);
240 
241 	nfct_filter_add_attr(filter, NFCT_FILTER_DST_IPV4, &filter_ipv4);
242 
243 	IPACMDBG("Ignore connections orignated from interface %s", param->ifname);
244 	iptodot("with ipv4 address", filter_ipv4.addr);
245 	nfct_filter_set_logic(filter,
246 												NFCT_FILTER_SRC_IPV4,
247 												NFCT_FILTER_LOGIC_NEGATIVE);
248 
249 	nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4);
250 
251 	/* Retrieve broadcast address */
252 	/* Intialize with 255.255.255.255 */
253 	uint32_t bc_ip_addr = 0xFFFFFFFF;
254 
255 	/* calculate broadcast address from addr and addr_mask */
256 	bc_ip_addr = (bc_ip_addr & (~param->addr_mask));
257 	bc_ip_addr = (bc_ip_addr | (param->ipv4_addr & param->addr_mask));
258 
259 	/* netfitler expecting in host-byte order */
260 	filter_ipv4.addr = bc_ip_addr;
261 	filter_ipv4.mask = 0xffffffff;
262 
263 	iptodot("with broadcast address", filter_ipv4.addr);
264 	nfct_filter_set_logic(filter,
265 												NFCT_FILTER_DST_IPV4,
266 												NFCT_FILTER_LOGIC_NEGATIVE);
267 
268 	nfct_filter_add_attr(filter, NFCT_FILTER_DST_IPV4, &filter_ipv4);
269 
270 	return 0;
271 }
272 
273 /* Function which sets up filters to ignore
274 		 connections to and from local interfaces */
IPA_Conntrack_Filters_Ignore_Local_Addrs(struct nfct_filter * filter)275 int IPACM_ConntrackClient::IPA_Conntrack_Filters_Ignore_Local_Addrs
276 (
277 	 struct nfct_filter *filter
278 )
279 {
280 	struct nfct_filter_ipv4 filter_ipv4;
281 
282 	/* ignore whatever is destined to or originates from broadcast ip address */
283 	filter_ipv4.addr = 0xffffffff;
284 	filter_ipv4.mask = 0xffffffff;
285 
286 	nfct_filter_set_logic(filter,
287 												NFCT_FILTER_DST_IPV4,
288 												NFCT_FILTER_LOGIC_NEGATIVE);
289 
290 	nfct_filter_add_attr(filter, NFCT_FILTER_DST_IPV4, &filter_ipv4);
291 
292 	nfct_filter_set_logic(filter,
293 												NFCT_FILTER_SRC_IPV4,
294 												NFCT_FILTER_LOGIC_NEGATIVE);
295 
296 	nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4);
297 
298 	return 0;
299 } /* IPA_Conntrack_Filters_Ignore_Local_Addrs() */
300 
301 /* Initialize TCP Filter */
IPA_Conntrack_TCP_Filter_Init(void)302 int IPACM_ConntrackClient::IPA_Conntrack_TCP_Filter_Init(void)
303 {
304 	int ret = 0;
305 	IPACM_ConntrackClient *pClient;
306 
307 	IPACMDBG("\n");
308 
309 	pClient = IPACM_ConntrackClient::GetInstance();
310 	if(pClient == NULL)
311 	{
312 		IPACMERR("unable to get conntrack client instance\n");
313 		return -1;
314 	}
315 
316 	ret = nfct_filter_set_logic(pClient->tcp_filter,
317 															NFCT_FILTER_L4PROTO,
318 															NFCT_FILTER_LOGIC_POSITIVE);
319 	if(ret == -1)
320 	{
321 		IPACMERR("Unable to set filter logic\n");
322 		return -1;
323 	}
324 
325 	/* set protocol filters as tcp and udp */
326 	nfct_filter_add_attr_u32(pClient->tcp_filter, NFCT_FILTER_L4PROTO, IPPROTO_TCP);
327 
328 
329 	struct nfct_filter_proto tcp_proto_state;
330 	tcp_proto_state.proto = IPPROTO_TCP;
331 	tcp_proto_state.state = TCP_CONNTRACK_ESTABLISHED;
332 
333 	ret = nfct_filter_set_logic(pClient->tcp_filter,
334 															NFCT_FILTER_L4PROTO_STATE,
335 															NFCT_FILTER_LOGIC_POSITIVE);
336 	if(ret == -1)
337 	{
338 		IPACMERR("unable to set filter logic\n");
339 		return -1;
340 	}
341 	nfct_filter_add_attr(pClient->tcp_filter,
342 											 NFCT_FILTER_L4PROTO_STATE,
343 											 &tcp_proto_state);
344 
345 
346 	tcp_proto_state.proto = IPPROTO_TCP;
347 	tcp_proto_state.state = TCP_CONNTRACK_FIN_WAIT;
348 	ret = nfct_filter_set_logic(pClient->tcp_filter,
349 															NFCT_FILTER_L4PROTO_STATE,
350 															NFCT_FILTER_LOGIC_POSITIVE);
351 	if(ret == -1)
352 	{
353 		IPACMERR("unable to set filter logic\n");
354 		return -1;
355 	}
356 
357 	nfct_filter_add_attr(pClient->tcp_filter,
358 											 NFCT_FILTER_L4PROTO_STATE,
359 											 &tcp_proto_state);
360 	return 0;
361 }
362 
363 
364 /* Initialize UDP Filter */
IPA_Conntrack_UDP_Filter_Init(void)365 int IPACM_ConntrackClient::IPA_Conntrack_UDP_Filter_Init(void)
366 {
367 	int ret = 0;
368 	IPACM_ConntrackClient *pClient = IPACM_ConntrackClient::GetInstance();
369 	if(pClient == NULL)
370 	{
371 		IPACMERR("unable to get conntrack client instance\n");
372 		return -1;
373 	}
374 
375 	ret = nfct_filter_set_logic(pClient->udp_filter,
376 															NFCT_FILTER_L4PROTO,
377 															NFCT_FILTER_LOGIC_POSITIVE);
378 	if(ret == -1)
379 	{
380 		IPACMERR("unable to set filter logic\n");
381 	}
382 	/* set protocol filters as tcp and udp */
383 	nfct_filter_add_attr_u32(pClient->udp_filter, NFCT_FILTER_L4PROTO, IPPROTO_UDP);
384 
385 	return 0;
386 }
387 
UDPConnTimeoutUpdate(void * ptr)388 void* IPACM_ConntrackClient::UDPConnTimeoutUpdate(void *ptr)
389 {
390 	NatApp *nat_inst = NULL;
391 	ptr = NULL;
392 #ifdef IPACM_DEBUG
393 	IPACMDBG("\n");
394 #endif
395 
396 	nat_inst = NatApp::GetInstance();
397 	if(nat_inst == NULL)
398 	{
399 		IPACMERR("unable to create nat instance\n");
400 		return NULL;
401 	}
402 
403 	while(1)
404 	{
405 		nat_inst->UpdateUDPTimeStamp();
406 		sleep(UDP_TIMEOUT_UPDATE);
407 	} /* end of while(1) loop */
408 
409 #ifdef IPACM_DEBUG
410 	IPACMDBG("Returning from %s() %d\n", __FUNCTION__, __LINE__);
411 #endif
412 
413 	return NULL;
414 }
415 
416 /* Thread to initialize TCP Conntrack Filters*/
TCPRegisterWithConnTrack(void *)417 void* IPACM_ConntrackClient::TCPRegisterWithConnTrack(void *)
418 {
419 	int ret;
420 	IPACM_ConntrackClient *pClient;
421 	unsigned subscrips = 0;
422 
423 	IPACMDBG("\n");
424 
425 	pClient = IPACM_ConntrackClient::GetInstance();
426 	if(pClient == NULL)
427 	{
428 		IPACMERR("unable to get conntrack client instance\n");
429 		return NULL;
430 	}
431 
432 	subscrips = (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY);
433 #ifdef CT_OPT
434 	subscrips |= NF_NETLINK_CONNTRACK_NEW;
435 #endif
436 
437 #ifdef FEATURE_IPACM_HAL
438 	if (pClient->fd_tcp < 0) {
439 		IPACMERR("unable to get conntrack TCP handle due to fd_tcp is invalid \n");
440 		return NULL;
441 	} else {
442 		pClient->tcp_hdl = nfct_open2(CONNTRACK, subscrips, pClient->fd_tcp);
443 	}
444 #else
445 	pClient->tcp_hdl = nfct_open(CONNTRACK, subscrips);
446 #endif
447 
448 	if(pClient->tcp_hdl == NULL)
449 	{
450 		PERROR("nfct_open failed on getting tcp_hdl\n");
451 		return NULL;
452 	}
453 
454 	/* Initialize the filter */
455 	ret = IPA_Conntrack_TCP_Filter_Init();
456 	if(ret == -1)
457 	{
458 		IPACMERR("Unable to initliaze TCP Filter\n");
459 		return NULL;
460 	}
461 
462 	/* Attach the filter to net filter handler */
463 	ret = nfct_filter_attach(nfct_fd(pClient->tcp_hdl), pClient->tcp_filter);
464 	if(ret == -1)
465 	{
466 		IPACMDBG("unable to attach TCP filter\n");
467 		return NULL;
468 	}
469 
470 	/* Register callback with netfilter handler */
471 	IPACMDBG_H("tcp handle:%pK, fd:%d\n", pClient->tcp_hdl, nfct_fd(pClient->tcp_hdl));
472 #ifndef CT_OPT
473 	nfct_callback_register(pClient->tcp_hdl,
474 			(nf_conntrack_msg_type)	(NFCT_T_UPDATE | NFCT_T_DESTROY | NFCT_T_NEW),
475 						IPAConntrackEventCB, NULL);
476 #else
477 	nfct_callback_register(pClient->tcp_hdl, (nf_conntrack_msg_type) NFCT_T_ALL, IPAConntrackEventCB, NULL);
478 #endif
479 
480 	/* Block to catch events from net filter connection track */
481 	/* nfct_catch() receives conntrack events from kernel-space, by default it
482 			 blocks waiting for events. */
483 	IPACMDBG("Waiting for events\n");
484 
485 ctcatch:
486 	ret = nfct_catch(pClient->tcp_hdl);
487 	if((ret == -1) && (errno != ENOMSG))
488 	{
489 		IPACMERR("(%d)(%d)(%s)\n", ret, errno, strerror(errno));
490 		return NULL;
491 	}
492 	else
493 	{
494 		IPACMDBG("ctcatch ret:%d, errno:%d\n", ret, errno);
495 		goto ctcatch;
496 	}
497 
498 	IPACMDBG("Exit from tcp thread\n");
499 
500 	/* destroy the filter.. this will not detach the filter */
501 	nfct_filter_destroy(pClient->tcp_filter);
502 	pClient->tcp_filter = NULL;
503 
504 	/* de-register the callback */
505 	nfct_callback_unregister(pClient->tcp_hdl);
506 	/* close the handle */
507 #ifdef FEATURE_IPACM_HAL
508 	nfct_close2(pClient->tcp_hdl, true);
509 #else
510 	nfct_close(pClient->tcp_hdl);
511 #endif
512 	pClient->tcp_hdl = NULL;
513 
514 	pthread_exit(NULL);
515 	return NULL;
516 }
517 
518 /* Thread to initialize UDP Conntrack Filters*/
UDPRegisterWithConnTrack(void *)519 void* IPACM_ConntrackClient::UDPRegisterWithConnTrack(void *)
520 {
521 	int ret;
522 	IPACM_ConntrackClient *pClient = NULL;
523 
524 	IPACMDBG("\n");
525 
526 	pClient = IPACM_ConntrackClient::GetInstance();
527 	if(pClient == NULL)
528 	{
529 		IPACMERR("unable to retrieve instance of conntrack client\n");
530 		return NULL;
531 	}
532 
533 #ifdef FEATURE_IPACM_HAL
534 	if (pClient->fd_udp < 0) {
535 		IPACMERR("unable to get conntrack UDP handle due to fd_udp is invalid \n");
536 		return NULL;
537 	} else {
538 		pClient->udp_hdl = nfct_open2(CONNTRACK,
539 					(NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY), pClient->fd_udp);
540 	}
541 #else
542 	pClient->udp_hdl = nfct_open(CONNTRACK,
543 					(NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY));
544 #endif
545 	if(pClient->udp_hdl == NULL)
546 	{
547 		PERROR("nfct_open failed on getting udp_hdl\n");
548 		return NULL;
549 	}
550 
551 	/* Initialize Filter */
552 	ret = IPA_Conntrack_UDP_Filter_Init();
553 	if(-1 == ret)
554 	{
555 		IPACMDBG("Unable to initalize udp filters\n");
556 		return NULL;
557 	}
558 
559 	/* Attach the filter to net filter handler */
560 	ret = nfct_filter_attach(nfct_fd(pClient->udp_hdl), pClient->udp_filter);
561 	if(ret == -1)
562 	{
563 		IPACMDBG("unable to attach the filter\n");
564 		return NULL;
565 	}
566 
567 	/* Register callback with netfilter handler */
568 	IPACMDBG_H("udp handle:%pK, fd:%d\n", pClient->udp_hdl, nfct_fd(pClient->udp_hdl));
569 	nfct_callback_register(pClient->udp_hdl,
570 			(nf_conntrack_msg_type)(NFCT_T_NEW | NFCT_T_DESTROY),
571 			IPAConntrackEventCB,
572 			NULL);
573 
574 	/* Block to catch events from net filter connection track */
575 ctcatch:
576 	ret = nfct_catch(pClient->udp_hdl);
577 	/* Due to conntrack dump, sequence number might mismatch for initial events. */
578 	if((ret == -1) && (errno != ENOMSG) && (errno != EILSEQ))
579 	{
580 		IPACMDBG("(%d)(%d)(%s)\n", ret, errno, strerror(errno));
581 		return NULL;
582 	}
583 	else
584 	{
585 		IPACMDBG("ctcatch ret:%d, errno:%d\n", ret, errno);
586 		goto ctcatch;
587 	}
588 
589 	IPACMDBG("Exit from udp thread with ret: %d\n", ret);
590 
591 	/* destroy the filter.. this will not detach the filter */
592 	nfct_filter_destroy(pClient->udp_filter);
593 	pClient->udp_filter = NULL;
594 
595 	/* de-register the callback */
596 	nfct_callback_unregister(pClient->udp_hdl);
597 	/* close the handle */
598 #ifdef FEATURE_IPACM_HAL
599 	nfct_close2(pClient->udp_hdl, true);
600 #else
601 	nfct_close(pClient->udp_hdl);
602 #endif
603 	pClient->udp_hdl = NULL;
604 
605 	pthread_exit(NULL);
606 	return NULL;
607 }
608 
609 /* Thread to initialize TCP Conntrack Filters*/
UNRegisterWithConnTrack(void)610 void IPACM_ConntrackClient::UNRegisterWithConnTrack(void)
611 {
612 	IPACM_ConntrackClient *pClient = NULL;
613 
614 	IPACMDBG("\n");
615 
616 	pClient = IPACM_ConntrackClient::GetInstance();
617 	if(pClient == NULL)
618 	{
619 		IPACMERR("unable to retrieve instance of conntrack client\n");
620 		return;
621 	}
622 
623 	/* destroy the TCP filter.. this will not detach the filter */
624 	if (pClient->tcp_filter) {
625 		nfct_filter_destroy(pClient->tcp_filter);
626 		pClient->tcp_filter = NULL;
627 	}
628 
629 	/* de-register the callback */
630 	if (pClient->tcp_hdl) {
631 		nfct_callback_unregister(pClient->tcp_hdl);
632 		/* close the handle */
633 		nfct_close(pClient->tcp_hdl);
634 		pClient->tcp_hdl = NULL;
635 	}
636 
637 	/* destroy the filter.. this will not detach the filter */
638 	if (pClient->udp_filter) {
639 		nfct_filter_destroy(pClient->udp_filter);
640 		pClient->udp_filter = NULL;
641 	}
642 
643 	/* de-register the callback */
644 	if (pClient->udp_hdl) {
645 		nfct_callback_unregister(pClient->udp_hdl);
646 		/* close the handle */
647 		nfct_close(pClient->udp_hdl);
648 		pClient->udp_hdl = NULL;
649 	}
650 
651 	pClient->fd_tcp = -1;
652 	pClient->fd_udp = -1;
653 
654 	return;
655 }
656 
UpdateUDPFilters(void * param,bool isWan)657 void IPACM_ConntrackClient::UpdateUDPFilters(void *param, bool isWan)
658 {
659 	static bool isIgnore = false;
660 	int ret = 0;
661 	IPACM_ConntrackClient *pClient = NULL;
662 
663 	pClient = IPACM_ConntrackClient::GetInstance();
664 	if(pClient == NULL)
665 	{
666 		IPACMERR("unable to retrieve conntrack client instance\n");
667 		return;
668 	}
669 
670 	if(pClient->udp_filter == NULL)
671 	{
672 		 return;
673 	}
674 
675 	if(!isWan)
676 	{
677 		IPA_Conntrack_Filters_Ignore_Local_Iface(pClient->udp_filter,
678 																		 (ipacm_event_iface_up *)param);
679 
680 		if(!isIgnore)
681 		{
682 			IPA_Conntrack_Filters_Ignore_Bridge_Addrs(pClient->udp_filter);
683 			IPA_Conntrack_Filters_Ignore_Local_Addrs(pClient->udp_filter);
684 			isIgnore = true;
685 		}
686 	}
687 
688 	/* Attach the filter to udp handle */
689 	if(pClient->udp_hdl != NULL)
690 	{
691 		IPACMDBG("attaching the filter to udp handle\n");
692 		ret = nfct_filter_attach(nfct_fd(pClient->udp_hdl), pClient->udp_filter);
693 		if(ret == -1)
694 		{
695 			PERROR("unable to attach the filter to udp handle\n");
696 			IPACMERR("udp handle:%pK, fd:%d Error: %d\n",pClient->udp_hdl, nfct_fd(pClient->udp_hdl), ret);
697 			return;
698 		}
699 	}
700 
701 	return;
702 }
703 
UpdateTCPFilters(void * param,bool isWan)704 void IPACM_ConntrackClient::UpdateTCPFilters(void *param, bool isWan)
705 {
706 	static bool isIgnore = false;
707 	int ret = 0;
708 	IPACM_ConntrackClient *pClient = NULL;
709 
710 	pClient = IPACM_ConntrackClient::GetInstance();
711 	if(pClient == NULL)
712 	{
713 		IPACMERR("unable to retrieve conntrack client instance\n");
714 		return;
715 	}
716 
717 	if(pClient->tcp_filter == NULL)
718 		return;
719 
720 	if(!isWan)
721 	{
722 		IPA_Conntrack_Filters_Ignore_Local_Iface(pClient->tcp_filter,
723 																	(ipacm_event_iface_up *)param);
724 
725 		if(!isIgnore)
726 		{
727 			IPA_Conntrack_Filters_Ignore_Bridge_Addrs(pClient->udp_filter);
728 			IPA_Conntrack_Filters_Ignore_Local_Addrs(pClient->udp_filter);
729 			isIgnore = true;
730 		}
731 	}
732 
733 	/* Attach the filter to tcp handle */
734 	if(pClient->tcp_hdl != NULL)
735 	{
736 		IPACMDBG("attaching the filter to tcp handle\n");
737 		ret = nfct_filter_attach(nfct_fd(pClient->tcp_hdl), pClient->tcp_filter);
738 		if(ret == -1)
739 		{
740 			PERROR("unable to attach the filter to tcp handle\n");
741 			IPACMERR("tcp handle:%pK, fd:%d Error: %d\n",pClient->tcp_hdl, nfct_fd(pClient->tcp_hdl), ret);
742 			return;
743 		}
744 	}
745 
746   return;
747 }
748 
749