1 /*
2 Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7 		* Redistributions of source code must retain the above copyright
8 			notice, this list of conditions and the following disclaimer.
9 		* Redistributions in binary form must reproduce the above
10 			copyright notice, this list of conditions and the following
11 			disclaimer in the documentation and/or other materials provided
12 			with the distribution.
13 		* Neither the name of The Linux Foundation nor the names of its
14 			contributors may be used to endorse or promote products derived
15 			from this software without specific prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 #include <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 	if(strlen(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name) >= sizeof(ifr.ifr_name))
178 	{
179 		IPACMERR("interface name overflows: len %zu\n",
180 			strlen(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name));
181 		close(fd);
182 		return -1;
183 	}
184 
185 	/* retrieve bridge interface ipv4 address */
186 	memset(&ifr, 0, sizeof(struct ifreq));
187 	ifr.ifr_addr.sa_family = AF_INET;
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 
391 	NatApp *nat_inst = NULL;
392 	ptr = NULL;
393 #ifdef IPACM_DEBUG
394 	IPACMDBG("\n");
395 #endif
396 
397 	nat_inst = NatApp::GetInstance();
398 	if(nat_inst == NULL)
399 	{
400 		IPACMERR("unable to create nat instance\n");
401 		return NULL;
402 	}
403 
404 	while(1)
405 	{
406 		nat_inst->UpdateUDPTimeStamp();
407 		sleep(UDP_TIMEOUT_UPDATE);
408 	} /* end of while(1) loop */
409 
410 #ifdef IPACM_DEBUG
411 	IPACMDBG("Returning from %s() %d\n", __FUNCTION__, __LINE__);
412 #endif
413 
414 	return NULL;
415 }
416 
417 /* Thread to initialize TCP Conntrack Filters*/
TCPRegisterWithConnTrack(void *)418 void* IPACM_ConntrackClient::TCPRegisterWithConnTrack(void *)
419 {
420 	int ret;
421 	IPACM_ConntrackClient *pClient;
422 	unsigned subscrips = 0;
423 
424 	IPACMDBG("\n");
425 
426 	pClient = IPACM_ConntrackClient::GetInstance();
427 	if(pClient == NULL)
428 	{
429 		IPACMERR("unable to get conntrack client instance\n");
430 		return NULL;
431 	}
432 
433 	subscrips = (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY);
434 #ifdef CT_OPT
435 	subscrips |= NF_NETLINK_CONNTRACK_NEW;
436 #endif
437 
438 #ifdef FEATURE_IPACM_HAL
439 	if (pClient->fd_tcp < 0) {
440 		IPACMERR("unable to get conntrack TCP handle due to fd_tcp is invalid \n");
441 		return NULL;
442 	} else {
443 		pClient->tcp_hdl = nfct_open2(CONNTRACK, subscrips, pClient->fd_tcp);
444 	}
445 #else
446 	pClient->tcp_hdl = nfct_open(CONNTRACK, subscrips);
447 #endif
448 
449 	if(pClient->tcp_hdl == NULL)
450 	{
451 		PERROR("nfct_open failed on getting tcp_hdl\n");
452 		return NULL;
453 	}
454 
455 	/* Initialize the filter */
456 	ret = IPA_Conntrack_TCP_Filter_Init();
457 	if(ret == -1)
458 	{
459 		IPACMERR("Unable to initliaze TCP Filter\n");
460 		return NULL;
461 	}
462 
463 	/* Attach the filter to net filter handler */
464 	ret = nfct_filter_attach(nfct_fd(pClient->tcp_hdl), pClient->tcp_filter);
465 	if(ret == -1)
466 	{
467 		IPACMDBG("unable to attach TCP filter\n");
468 		return NULL;
469 	}
470 
471 	/* Register callback with netfilter handler */
472 	IPACMDBG_H("tcp handle:%p, fd:%d\n", pClient->tcp_hdl, nfct_fd(pClient->tcp_hdl));
473 #ifndef CT_OPT
474 	nfct_callback_register(pClient->tcp_hdl,
475 			(nf_conntrack_msg_type)	(NFCT_T_UPDATE | NFCT_T_DESTROY | NFCT_T_NEW),
476 						IPAConntrackEventCB, NULL);
477 #else
478 	nfct_callback_register(pClient->tcp_hdl, (nf_conntrack_msg_type) NFCT_T_ALL, IPAConntrackEventCB, NULL);
479 #endif
480 
481 	/* Block to catch events from net filter connection track */
482 	/* nfct_catch() receives conntrack events from kernel-space, by default it
483 			 blocks waiting for events. */
484 	IPACMDBG("Waiting for events\n");
485 
486 	ret = nfct_catch(pClient->tcp_hdl);
487 	if(ret == -1)
488 	{
489 		IPACMERR("(%d)(%s)\n", ret, strerror(errno));
490 		return NULL;
491 	}
492 
493 	IPACMDBG("Exit from tcp thread\n");
494 
495 	/* destroy the filter.. this will not detach the filter */
496 	nfct_filter_destroy(pClient->tcp_filter);
497 	pClient->tcp_filter = NULL;
498 
499 	/* de-register the callback */
500 	nfct_callback_unregister(pClient->tcp_hdl);
501 	/* close the handle */
502 #ifdef FEATURE_IPACM_HAL
503 	nfct_close2(pClient->tcp_hdl, true);
504 #else
505 	nfct_close(pClient->tcp_hdl);
506 #endif
507 	pClient->tcp_hdl = NULL;
508 
509 	pthread_exit(NULL);
510 	return NULL;
511 }
512 
513 /* Thread to initialize UDP Conntrack Filters*/
UDPRegisterWithConnTrack(void *)514 void* IPACM_ConntrackClient::UDPRegisterWithConnTrack(void *)
515 {
516 	int ret;
517 	IPACM_ConntrackClient *pClient = NULL;
518 
519 	IPACMDBG("\n");
520 
521 	pClient = IPACM_ConntrackClient::GetInstance();
522 	if(pClient == NULL)
523 	{
524 		IPACMERR("unable to retrieve instance of conntrack client\n");
525 		return NULL;
526 	}
527 
528 #ifdef FEATURE_IPACM_HAL
529 	if (pClient->fd_udp < 0) {
530 		IPACMERR("unable to get conntrack UDP handle due to fd_udp is invalid \n");
531 		return NULL;
532 	} else {
533 		pClient->udp_hdl = nfct_open2(CONNTRACK,
534 					(NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY), pClient->fd_udp);
535 	}
536 #else
537 	pClient->udp_hdl = nfct_open(CONNTRACK,
538 					(NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY));
539 #endif
540 	if(pClient->udp_hdl == NULL)
541 	{
542 		PERROR("nfct_open failed on getting udp_hdl\n");
543 		return NULL;
544 	}
545 
546 	/* Initialize Filter */
547 	ret = IPA_Conntrack_UDP_Filter_Init();
548 	if(-1 == ret)
549 	{
550 		IPACMDBG("Unable to initalize udp filters\n");
551 		return NULL;
552 	}
553 
554 	/* Attach the filter to net filter handler */
555 	ret = nfct_filter_attach(nfct_fd(pClient->udp_hdl), pClient->udp_filter);
556 	if(ret == -1)
557 	{
558 		IPACMDBG("unable to attach the filter\n");
559 		return NULL;
560 	}
561 
562 	/* Register callback with netfilter handler */
563 	IPACMDBG_H("udp handle:%p, fd:%d\n", pClient->udp_hdl, nfct_fd(pClient->udp_hdl));
564 	nfct_callback_register(pClient->udp_hdl,
565 			(nf_conntrack_msg_type)(NFCT_T_NEW | NFCT_T_DESTROY),
566 			IPAConntrackEventCB,
567 			NULL);
568 
569 	/* Block to catch events from net filter connection track */
570 ctcatch:
571 	ret = nfct_catch(pClient->udp_hdl);
572 	if(ret == -1)
573 	{
574 		IPACMDBG("(%d)(%s)\n", ret, strerror(errno));
575 		return NULL;
576 	}
577 	else
578 	{
579 		IPACMDBG("ctcatch ret:%d\n", ret);
580 		goto ctcatch;
581 	}
582 
583 	IPACMDBG("Exit from udp thread with ret: %d\n", ret);
584 
585 	/* destroy the filter.. this will not detach the filter */
586 	nfct_filter_destroy(pClient->udp_filter);
587 	pClient->udp_filter = NULL;
588 
589 	/* de-register the callback */
590 	nfct_callback_unregister(pClient->udp_hdl);
591 	/* close the handle */
592 #ifdef FEATURE_IPACM_HAL
593 	nfct_close2(pClient->udp_hdl, true);
594 #else
595 	nfct_close(pClient->udp_hdl);
596 #endif
597 	pClient->udp_hdl = NULL;
598 
599 	pthread_exit(NULL);
600 	return NULL;
601 }
602 
603 /* Thread to initialize TCP Conntrack Filters*/
UNRegisterWithConnTrack(void)604 void IPACM_ConntrackClient::UNRegisterWithConnTrack(void)
605 {
606 	IPACM_ConntrackClient *pClient = NULL;
607 
608 	IPACMDBG("\n");
609 
610 	pClient = IPACM_ConntrackClient::GetInstance();
611 	if(pClient == NULL)
612 	{
613 		IPACMERR("unable to retrieve instance of conntrack client\n");
614 		return;
615 	}
616 
617 	/* destroy the TCP filter.. this will not detach the filter */
618 	if (pClient->tcp_filter) {
619 		nfct_filter_destroy(pClient->tcp_filter);
620 		pClient->tcp_filter = NULL;
621 	}
622 
623 	/* de-register the callback */
624 	if (pClient->tcp_hdl) {
625 		nfct_callback_unregister(pClient->tcp_hdl);
626 		/* close the handle */
627 		nfct_close(pClient->tcp_hdl);
628 		pClient->tcp_hdl = NULL;
629 	}
630 
631 	/* destroy the filter.. this will not detach the filter */
632 	if (pClient->udp_filter) {
633 		nfct_filter_destroy(pClient->udp_filter);
634 		pClient->udp_filter = NULL;
635 	}
636 
637 	/* de-register the callback */
638 	if (pClient->udp_hdl) {
639 		nfct_callback_unregister(pClient->udp_hdl);
640 		/* close the handle */
641 		nfct_close(pClient->udp_hdl);
642 		pClient->udp_hdl = NULL;
643 	}
644 
645 	pClient->fd_tcp = -1;
646 	pClient->fd_udp = -1;
647 
648 	return;
649 }
650 
UpdateUDPFilters(void * param,bool isWan)651 void IPACM_ConntrackClient::UpdateUDPFilters(void *param, bool isWan)
652 {
653 	static bool isIgnore = false;
654 	int ret = 0;
655 	IPACM_ConntrackClient *pClient = NULL;
656 
657 	pClient = IPACM_ConntrackClient::GetInstance();
658 	if(pClient == NULL)
659 	{
660 		IPACMERR("unable to retrieve conntrack client instance\n");
661 		return;
662 	}
663 
664 	if(pClient->udp_filter == NULL)
665 	{
666 		 return;
667 	}
668 
669 	if(!isWan)
670 	{
671 		IPA_Conntrack_Filters_Ignore_Local_Iface(pClient->udp_filter,
672 																		 (ipacm_event_iface_up *)param);
673 
674 		if(!isIgnore)
675 		{
676 			IPA_Conntrack_Filters_Ignore_Bridge_Addrs(pClient->udp_filter);
677 			IPA_Conntrack_Filters_Ignore_Local_Addrs(pClient->udp_filter);
678 			isIgnore = true;
679 		}
680 	}
681 
682 	/* Attach the filter to udp handle */
683 	if(pClient->udp_hdl != NULL)
684 	{
685 		IPACMDBG("attaching the filter to udp handle\n");
686 		ret = nfct_filter_attach(nfct_fd(pClient->udp_hdl), pClient->udp_filter);
687 		if(ret == -1)
688 		{
689 			PERROR("unable to attach the filter to udp handle\n");
690 			IPACMERR("udp handle:%p, fd:%d Error: %d\n",pClient->udp_hdl, nfct_fd(pClient->udp_hdl), ret);
691 			return;
692 		}
693 	}
694 
695 	return;
696 }
697 
UpdateTCPFilters(void * param,bool isWan)698 void IPACM_ConntrackClient::UpdateTCPFilters(void *param, bool isWan)
699 {
700 	static bool isIgnore = false;
701 	int ret = 0;
702 	IPACM_ConntrackClient *pClient = NULL;
703 
704 	pClient = IPACM_ConntrackClient::GetInstance();
705 	if(pClient == NULL)
706 	{
707 		IPACMERR("unable to retrieve conntrack client instance\n");
708 		return;
709 	}
710 
711 	if(pClient->tcp_filter == NULL)
712 		return;
713 
714 	if(!isWan)
715 	{
716 		IPA_Conntrack_Filters_Ignore_Local_Iface(pClient->tcp_filter,
717 																	(ipacm_event_iface_up *)param);
718 
719 		if(!isIgnore)
720 		{
721 			IPA_Conntrack_Filters_Ignore_Bridge_Addrs(pClient->udp_filter);
722 			IPA_Conntrack_Filters_Ignore_Local_Addrs(pClient->udp_filter);
723 			isIgnore = true;
724 		}
725 	}
726 
727 	/* Attach the filter to tcp handle */
728 	if(pClient->tcp_hdl != NULL)
729 	{
730 		IPACMDBG("attaching the filter to tcp handle\n");
731 		ret = nfct_filter_attach(nfct_fd(pClient->tcp_hdl), pClient->tcp_filter);
732 		if(ret == -1)
733 		{
734 			PERROR("unable to attach the filter to tcp handle\n");
735 			IPACMERR("tcp handle:%p, fd:%d Error: %d\n",pClient->tcp_hdl, nfct_fd(pClient->tcp_hdl), ret);
736 			return;
737 		}
738 	}
739 
740   return;
741 }
742 
743