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