1 // SoftEther VPN Source Code - Developer Edition Master Branch
2 // Cedar Communication Module
3 
4 
5 // Listener.c
6 // Listener module
7 
8 #include "Listener.h"
9 
10 #include "Cedar.h"
11 #include "Connection.h"
12 #include "Logging.h"
13 #include "Server.h"
14 #include "Session.h"
15 
16 #include "Mayaqua/Mayaqua.h"
17 #include "Mayaqua/Memory.h"
18 #include "Mayaqua/Object.h"
19 #include "Mayaqua/Str.h"
20 
21 static bool disable_dos = false;
22 static UINT max_connections_per_ip = DEFAULT_MAX_CONNECTIONS_PER_IP;
23 static UINT max_unestablished_connections = DEFAULT_MAX_UNESTABLISHED_CONNECTIONS;
24 static bool listener_proc_recv_rpc = false;
25 
26 // Set the flag of whether to response to the RPC of RUDP
ListenerSetProcRecvRpcEnable(bool b)27 void ListenerSetProcRecvRpcEnable(bool b)
28 {
29 	listener_proc_recv_rpc = b;
30 }
31 
32 // Get the number of allowed outstanding connections
GetMaxUnestablishedConnections()33 UINT GetMaxUnestablishedConnections()
34 {
35 	return max_unestablished_connections;
36 }
37 
38 // Set the number of allowed outstanding connections
SetMaxUnestablishedConnections(UINT num)39 void SetMaxUnestablishedConnections(UINT num)
40 {
41 	if (num == 0)
42 	{
43 		num = DEFAULT_MAX_UNESTABLISHED_CONNECTIONS;
44 	}
45 
46 	max_unestablished_connections = MAX(num, max_connections_per_ip);
47 }
48 
49 // Get the maximum number of connections per IP address
GetMaxConnectionsPerIp()50 UINT GetMaxConnectionsPerIp()
51 {
52 	return max_connections_per_ip;
53 }
54 
55 // Set the maximum number of connections per IP address
SetMaxConnectionsPerIp(UINT num)56 void SetMaxConnectionsPerIp(UINT num)
57 {
58 	if (num == 0)
59 	{
60 		num = DEFAULT_MAX_CONNECTIONS_PER_IP;
61 	}
62 	max_connections_per_ip = MAX(num, MIN_MAX_CONNECTIONS_PER_IP);
63 }
64 
65 // Enable the DoS defense
EnableDosProtect()66 void EnableDosProtect()
67 {
68 	disable_dos = false;
69 }
70 
71 // Disable the DoS defense
DisableDosProtect()72 void DisableDosProtect()
73 {
74 	disable_dos = true;
75 }
76 
77 // An UDP packet has been received
UDPReceivedPacket(CEDAR * cedar,SOCK * s,IP * ip,UINT port,void * data,UINT size)78 void UDPReceivedPacket(CEDAR *cedar, SOCK *s, IP *ip, UINT port, void *data, UINT size)
79 {
80 	SESSION *session;
81 	UINT *key32;
82 	UCHAR *buf;
83 	CONNECTION *c;
84 	// Validate arguments
85 	if (s == NULL || ip == NULL || data == NULL || size == 0 || cedar == NULL)
86 	{
87 		return;
88 	}
89 
90 	if (size < 16)
91 	{
92 		// Ignore since the packet size is not enough
93 		return;
94 	}
95 	buf = (UCHAR *)data;
96 	key32 = (UINT *)(buf + 4);
97 
98 
99 	// Get the session from the Key32 value
100 	session = GetSessionFromUDPEntry(cedar, Endian32(*key32));
101 	if (session == NULL)
102 	{
103 		Debug("Invalid UDP Session Key 32: 0x%X\n", *key32);
104 		return;
105 	}
106 
107 	c = session->Connection;
108 
109 	// Write the data
110 	PutUDPPacketData(c, buf, size);
111 
112 	// Rewrite the UDP socket associated with the connection
113 	Lock(c->lock);
114 	{
115 		if (c->Protocol == CONNECTION_UDP)
116 		{
117 			if (c->Udp->s != s)
118 			{
119 				if (c->Udp->s != NULL)
120 				{
121 					ReleaseSock(c->Udp->s);
122 				}
123 				AddRef(s->ref);
124 				c->Udp->s = s;
125 			}
126 			Copy(&c->Udp->ip, ip, sizeof(UINT));
127 			c->Udp->port = port;
128 		}
129 	}
130 	Unlock(c->lock);
131 
132 	// Invoke the Cancel
133 	Cancel(session->Cancel1);
134 
135 	// Release the session
136 	ReleaseSession(session);
137 }
138 
139 // Thread that processes the accepted TCP connection
TCPAcceptedThread(THREAD * t,void * param)140 void TCPAcceptedThread(THREAD *t, void *param)
141 {
142 	TCP_ACCEPTED_PARAM *data;
143 	LISTENER *r;
144 	SOCK *s;
145 	CONNECTION *c;
146 	bool flag1;
147 	char tmp[128];
148 	// Validate arguments
149 	if (t == NULL || param == NULL)
150 	{
151 		return;
152 	}
153 
154 	// Initialize
155 	data = (TCP_ACCEPTED_PARAM *)param;
156 	r = data->r;
157 	s = data->s;
158 	AddRef(r->ref);
159 	AddRef(s->ref);
160 
161 	// Create a connection
162 	c = NewServerConnection(r->Cedar, s, t);
163 
164 	AddRef(r->ref);
165 	c->Listener = r;
166 
167 	// Register to Cedar as a transient connection
168 	AddConnection(c->Cedar, c);
169 
170 	NoticeThreadInit(t);
171 
172 	AcceptInit(s);
173 	StrCpy(c->ClientHostname, sizeof(c->ClientHostname), s->RemoteHostname);
174 	IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
175 	if (IS_SPECIAL_PORT(s->RemotePort) == false)
176 	{
177 		SLog(r->Cedar, "LS_LISTENER_ACCEPT", r->Port, tmp, s->RemoteHostname, s->RemotePort);
178 	}
179 
180 	// Reception
181 	ConnectionAccept(c);
182 	flag1 = c->flag1;
183 
184 	// Release
185 	SLog(r->Cedar, "LS_CONNECTION_END_1", c->Name);
186 	ReleaseListener(c->Listener);
187 	c->Listener = NULL;
188 	ReleaseConnection(c);
189 
190 	// Release
191 	if (flag1 == false)
192 	{
193 		Debug("%s %u flag1 == false\n", __FILE__, __LINE__);
194 		IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
195 
196 		if (IS_SPECIAL_PORT(s->RemotePort) == false)
197 		{
198 			SLog(r->Cedar, "LS_LISTENER_DISCONNECT", tmp, s->RemotePort);
199 		}
200 		Disconnect(s);
201 	}
202 	ReleaseSock(s);
203 	ReleaseListener(r);
204 }
205 
206 // Jump here if there is accepted connection in the TCP
TCPAccepted(LISTENER * r,SOCK * s)207 void TCPAccepted(LISTENER *r, SOCK *s)
208 {
209 	TCP_ACCEPTED_PARAM *data;
210 	THREAD *t;
211 	char tmp[MAX_SIZE];
212 	UINT num_clients_from_this_ip = 0;
213 	CEDAR *cedar;
214 	// Validate arguments
215 	if (r == NULL || s == NULL)
216 	{
217 		return;
218 	}
219 
220 	cedar = r->Cedar;
221 
222 	num_clients_from_this_ip = GetNumIpClient(&s->RemoteIP);
223 
224 
225 	IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
226 
227 	data = ZeroMalloc(sizeof(TCP_ACCEPTED_PARAM));
228 	data->r = r;
229 	data->s = s;
230 
231 	if (r->ThreadProc == TCPAcceptedThread)
232 	{
233 		Inc(cedar->AcceptingSockets);
234 	}
235 
236 	t = NewThread(r->ThreadProc, data);
237 	WaitThreadInit(t);
238 	Free(data);
239 	ReleaseThread(t);
240 }
241 
242 
243 // UDP listener main loop
ListenerUDPMainLoop(LISTENER * r)244 void ListenerUDPMainLoop(LISTENER *r)
245 {
246 	UCHAR *data;
247 	// Validate arguments
248 	if (r == NULL)
249 	{
250 		return;
251 	}
252 
253 	Debug("ListenerUDPMainLoop Starts.\n");
254 	r->Status = LISTENER_STATUS_TRYING;
255 
256 	while (true)
257 	{
258 		// Try to listen on the UDP port
259 		while (true)
260 		{
261 			// Stop flag inspection
262 			if (r->Halt)
263 			{
264 				// Stop
265 				return;
266 			}
267 
268 			Debug("NewUDP()\n");
269 			r->Sock = NewUDPEx2(r->Port, false, &r->Cedar->Server->ListenIP);
270 			if (r->Sock != NULL)
271 			{
272 				// Wait success
273 				break;
274 			}
275 
276 			// Wait failure
277 			Debug("Failed to NewUDP.\n");
278 			Wait(r->Event, LISTEN_RETRY_TIME);
279 
280 			// Stop flag inspection
281 			if (r->Halt)
282 			{
283 				Debug("UDP Halt.\n");
284 				return;
285 			}
286 		}
287 
288 		r->Status = LISTENER_STATUS_LISTENING;
289 		Debug("Start Listening at UDP Port %u.\n", r->Sock->LocalPort);
290 
291 		// Stop flag inspection
292 		if (r->Halt)
293 		{
294 			// Stop
295 			goto STOP;
296 		}
297 
298 		// Allocate the buffer area
299 		data = Malloc(UDP_PACKET_SIZE);
300 
301 		// Read the next packet
302 		while (true)
303 		{
304 			IP src_ip;
305 			UINT src_port;
306 			UINT size;
307 			SOCKSET set;
308 
309 			InitSockSet(&set);
310 			AddSockSet(&set, r->Sock);
311 			Select(&set, SELECT_TIME, NULL, NULL);
312 
313 			size = RecvFrom(r->Sock, &src_ip, &src_port, data, UDP_PACKET_SIZE);
314 			if (((size == 0) && (r->Sock->IgnoreRecvErr == false)) || r->Halt)
315 			{
316 				// Error has occurred
317 STOP:
318 				Disconnect(r->Sock);
319 				ReleaseSock(r->Sock);
320 				r->Sock = NULL;
321 				Debug("UDP Listen Stopped.\n");
322 				Free(data);
323 				break;
324 			}
325 
326 			// Received an UDP packet
327 			if (size != SOCK_LATER)
328 			{
329 				UDPReceivedPacket(r->Cedar, r->Sock, &src_ip, src_port, data, size);
330 			}
331 		}
332 	}
333 }
334 
335 // RPC reception procedure
ListenerRUDPRpcRecvProc(RUDP_STACK * r,UDPPACKET * p)336 bool ListenerRUDPRpcRecvProc(RUDP_STACK *r, UDPPACKET *p)
337 {
338 	return false;
339 }
340 
341 // TCP listener main loop
ListenerTCPMainLoop(LISTENER * r)342 void ListenerTCPMainLoop(LISTENER *r)
343 {
344 	SOCK *new_sock;
345 	SOCK *s;
346 	// Validate arguments
347 	if (r == NULL)
348 	{
349 		return;
350 	}
351 
352 	Debug("ListenerTCPMainLoop Starts.\n");
353 	r->Status = LISTENER_STATUS_TRYING;
354 
355 	while (true)
356 	{
357 		bool first_failed = true;
358 		Debug("Status = LISTENER_STATUS_TRYING\n");
359 		r->Status = LISTENER_STATUS_TRYING;
360 
361 		// Try to Listen
362 		while (true)
363 		{
364 			UINT interval;
365 			// Stop flag inspection
366 			if (r->Halt)
367 			{
368 				// Stop
369 				return;
370 			}
371 
372 			s = NULL;
373 
374 			if (r->Protocol == LISTENER_TCP)
375 			{
376 				if (r->ShadowIPv6 == false)
377 				{
378 					if (r->Cedar->Server == NULL)
379 					{
380 						s = ListenEx2(r->Port, r->LocalOnly, r->EnableConditionalAccept, NULL);
381 					}
382 					else
383 					{
384 						s = ListenEx2(r->Port, r->LocalOnly, r->EnableConditionalAccept, &r->Cedar->Server->ListenIP);
385 					}
386 				}
387 				else
388 				{
389 					s = ListenEx6(r->Port, r->LocalOnly);
390 				}
391 			}
392 			else if (r->Protocol == LISTENER_INPROC)
393 			{
394 				s = ListenInProc();
395 			}
396 			else if (r->Protocol == LISTENER_RUDP)
397 			{
398 				s = ListenRUDPEx(VPN_RUDP_SVC_NAME, NULL, ListenerRUDPRpcRecvProc, NULL, 0, false, false, r->NatTGlobalUdpPort, r->RandPortId, &r->Cedar->Server->ListenIP);
399 			}
400 			else if (r->Protocol == LISTENER_ICMP)
401 			{
402 				s = ListenRUDPEx(VPN_RUDP_SVC_NAME, NULL, ListenerRUDPRpcRecvProc, NULL, MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4),
403 					true, false, NULL, 0, &r->Cedar->Server->ListenIP);
404 			}
405 			else if (r->Protocol == LISTENER_DNS)
406 			{
407 				s = ListenRUDPEx(VPN_RUDP_SVC_NAME, NULL, ListenerRUDPRpcRecvProc, NULL, 53, true, true, NULL, 0, &r->Cedar->Server->ListenIP);
408 			}
409 			else if (r->Protocol == LISTENER_REVERSE)
410 			{
411 				s = ListenReverse();
412 			}
413 
414 			if (s != NULL)
415 			{
416 				// Listen success
417 				AddRef(s->ref);
418 
419 				Lock(r->lock);
420 				{
421 					r->Sock = s;
422 				}
423 				Unlock(r->lock);
424 
425 				if (r->ShadowIPv6 == false && r->Protocol == LISTENER_TCP)
426 				{
427 					SLog(r->Cedar, "LS_LISTENER_START_2", r->Port);
428 				}
429 				break;
430 			}
431 
432 			// Listen failure
433 			if (first_failed)
434 			{
435 				first_failed = false;
436 				if (r->ShadowIPv6 == false && r->Protocol == LISTENER_TCP)
437 				{
438 					SLog(r->Cedar, "LS_LISTENER_START_3", r->Port, LISTEN_RETRY_TIME / 1000);
439 				}
440 			}
441 
442 			interval = LISTEN_RETRY_TIME;
443 
444 			if (r->ShadowIPv6)
445 			{
446 				if (IsIPv6Supported() == false)
447 				{
448 					interval = LISTEN_RETRY_TIME_NOIPV6;
449 
450 					Debug("IPv6 is not supported.\n");
451 				}
452 			}
453 
454 			Wait(r->Event, interval);
455 
456 			// Stop flag inspection
457 			if (r->Halt)
458 			{
459 				// Stop
460 				Debug("Listener Halt.\n");
461 				return;
462 			}
463 		}
464 
465 		r->Status = LISTENER_STATUS_LISTENING;
466 		Debug("Status = LISTENER_STATUS_LISTENING\n");
467 
468 		// Stop flag inspection
469 		if (r->Halt)
470 		{
471 			// Stop
472 			goto STOP;
473 		}
474 
475 		// Accept loop
476 		while (true)
477 		{
478 			// Accept
479 			Debug("Accept()\n");
480 			new_sock = Accept(s);
481 			if (new_sock != NULL)
482 			{
483 				// Accept success
484 				Debug("Accepted.\n");
485 				TCPAccepted(r, new_sock);
486 				ReleaseSock(new_sock);
487 			}
488 			else
489 			{
490 STOP:
491 				Debug("Accept Canceled.\n");
492 				// Failed to accept (socket is destroyed)
493 				// Close the listening socket
494 				Disconnect(s);
495 				ReleaseSock(s);
496 				s = NULL;
497 
498 				Lock(r->lock);
499 				{
500 					if (r->Sock != NULL)
501 					{
502 						s = r->Sock;
503 						r->Sock = NULL;
504 					}
505 				}
506 				Unlock(r->lock);
507 
508 				if (s != NULL)
509 				{
510 					ReleaseSock(s);
511 				}
512 
513 				s = NULL;
514 
515 				break;
516 			}
517 		}
518 
519 		// Stop flag inspection
520 		if (r->Halt)
521 		{
522 			// Stop
523 			Debug("Listener Halt.\n");
524 			return;
525 		}
526 	}
527 }
528 
529 //  Listener Thread
ListenerThread(THREAD * thread,void * param)530 void ListenerThread(THREAD *thread, void *param)
531 {
532 	LISTENER *r;
533 	// Validate arguments
534 	if (thread == NULL || param == NULL)
535 	{
536 		return;
537 	}
538 
539 	// Initialize
540 	r = (LISTENER *)param;
541 	AddRef(r->ref);
542 	r->Thread = thread;
543 	AddRef(thread->ref);
544 	NoticeThreadInit(thread);
545 
546 	// Main loop
547 	switch (r->Protocol)
548 	{
549 	case LISTENER_TCP:
550 	case LISTENER_INPROC:
551 	case LISTENER_RUDP:
552 	case LISTENER_DNS:
553 	case LISTENER_ICMP:
554 	case LISTENER_REVERSE:
555 		// TCP or other stream-based protocol
556 		ListenerTCPMainLoop(r);
557 		break;
558 
559 	case LISTENER_UDP:
560 		// UDP protocol
561 		ListenerUDPMainLoop(r);
562 		break;
563 	}
564 
565 	// Release
566 	ReleaseListener(r);
567 }
568 
569 // Shutdown the Listener
StopListener(LISTENER * r)570 void StopListener(LISTENER *r)
571 {
572 	UINT port;
573 	SOCK *s = NULL;
574 	// Validate arguments
575 	if (r == NULL)
576 	{
577 		return;
578 	}
579 
580 	Lock(r->lock);
581 	if (r->Halt)
582 	{
583 		Unlock(r->lock);
584 		return;
585 	}
586 
587 	// Stop flag set
588 	r->Halt = true;
589 
590 	if (r->Sock != NULL)
591 	{
592 		s = r->Sock;
593 
594 		AddRef(s->ref);
595 	}
596 
597 	Unlock(r->lock);
598 
599 	port = r->Port;
600 
601 	if (r->ShadowIPv6 == false && r->Protocol == LISTENER_TCP)
602 	{
603 		SLog(r->Cedar, "LS_LISTENER_STOP_1", port);
604 	}
605 
606 	// Close the socket
607 	if (s != NULL)
608 	{
609 		Disconnect(s);
610 		ReleaseSock(s);
611 		s = NULL;
612 	}
613 
614 	// Set the event
615 	Set(r->Event);
616 
617 	// Wait for stopping the thread
618 	WaitThread(r->Thread, INFINITE);
619 
620 	// Stop the shadow listener
621 	if (r->ShadowIPv6 == false)
622 	{
623 		if (r->ShadowListener != NULL)
624 		{
625 			StopListener(r->ShadowListener);
626 
627 			ReleaseListener(r->ShadowListener);
628 
629 			r->ShadowListener = NULL;
630 		}
631 	}
632 
633 	if (r->ShadowIPv6 == false && r->Protocol == LISTENER_TCP)
634 	{
635 		SLog(r->Cedar, "LS_LISTENER_STOP_2", port);
636 	}
637 }
638 
639 // Cleanup the listener
CleanupListener(LISTENER * r)640 void CleanupListener(LISTENER *r)
641 {
642 	UINT i = 0;
643 	// Validate arguments
644 	if (r == NULL)
645 	{
646 		return;
647 	}
648 
649 
650 	if (r->Sock != NULL)
651 	{
652 		ReleaseSock(r->Sock);
653 	}
654 
655 	DeleteLock(r->lock);
656 	ReleaseThread(r->Thread);
657 	ReleaseEvent(r->Event);
658 
659 	ReleaseCedar(r->Cedar);
660 
661 	Free(r);
662 }
663 
664 // Release the listener
ReleaseListener(LISTENER * r)665 void ReleaseListener(LISTENER *r)
666 {
667 	// Validate arguments
668 	if (r == NULL)
669 	{
670 		return;
671 	}
672 
673 	if (Release(r->ref) == 0)
674 	{
675 		CleanupListener(r);
676 	}
677 }
678 
679 // Comparison function of UDP entry list
CompareUDPEntry(void * p1,void * p2)680 int CompareUDPEntry(void *p1, void *p2)
681 {
682 	UDP_ENTRY *e1, *e2;
683 	if (p1 == NULL || p2 == NULL)
684 	{
685 		return 0;
686 	}
687 	e1 = *(UDP_ENTRY **)p1;
688 	e2 = *(UDP_ENTRY **)p2;
689 	if (e1 == NULL || e2 == NULL)
690 	{
691 		return 0;
692 	}
693 
694 	if (e1->SessionKey32 > e2->SessionKey32)
695 	{
696 		return 1;
697 	}
698 	else if (e1->SessionKey32 == e2->SessionKey32)
699 	{
700 		return 0;
701 	}
702 	else
703 	{
704 		return -1;
705 	}
706 }
707 
708 // Comparison function of the listener
CompareListener(void * p1,void * p2)709 int CompareListener(void *p1, void *p2)
710 {
711 	LISTENER *r1, *r2;
712 	if (p1 == NULL || p2 == NULL)
713 	{
714 		return 0;
715 	}
716 	r1 = *(LISTENER **)p1;
717 	r2 = *(LISTENER **)p2;
718 	if (r1 == NULL || r2 == NULL)
719 	{
720 		return 0;
721 	}
722 
723 	if (r1->Protocol > r2->Protocol)
724 	{
725 		return 1;
726 	}
727 	else if (r1->Protocol < r2->Protocol)
728 	{
729 		return -1;
730 	}
731 	else if (r1->Port > r2->Port)
732 	{
733 		return 1;
734 	}
735 	else if (r1->Port < r2->Port)
736 	{
737 		return -1;
738 	}
739 	else
740 	{
741 		return 0;
742 	}
743 }
744 
745 // Create a New Listener
NewListener(CEDAR * cedar,UINT proto,UINT port)746 LISTENER *NewListener(CEDAR *cedar, UINT proto, UINT port)
747 {
748 	return NewListenerEx(cedar, proto, port, TCPAcceptedThread, NULL);
749 }
NewListenerEx(CEDAR * cedar,UINT proto,UINT port,THREAD_PROC * proc,void * thread_param)750 LISTENER *NewListenerEx(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param)
751 {
752 	return NewListenerEx2(cedar, proto, port, proc, thread_param, false);
753 }
NewListenerEx2(CEDAR * cedar,UINT proto,UINT port,THREAD_PROC * proc,void * thread_param,bool local_only)754 LISTENER *NewListenerEx2(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only)
755 {
756 	return NewListenerEx3(cedar, proto, port, proc, thread_param, local_only, false);
757 }
NewListenerEx3(CEDAR * cedar,UINT proto,UINT port,THREAD_PROC * proc,void * thread_param,bool local_only,bool shadow_ipv6)758 LISTENER *NewListenerEx3(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only, bool shadow_ipv6)
759 {
760 	return NewListenerEx4(cedar, proto, port, proc, thread_param, local_only, shadow_ipv6, NULL, 0);
761 }
NewListenerEx4(CEDAR * cedar,UINT proto,UINT port,THREAD_PROC * proc,void * thread_param,bool local_only,bool shadow_ipv6,volatile UINT * natt_global_udp_port,UCHAR rand_port_id)762 LISTENER *NewListenerEx4(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only, bool shadow_ipv6,
763 						 volatile UINT *natt_global_udp_port, UCHAR rand_port_id)
764 {
765 	return NewListenerEx5(cedar, proto, port, proc, thread_param,
766 		local_only, shadow_ipv6, natt_global_udp_port, rand_port_id, false);
767 }
NewListenerEx5(CEDAR * cedar,UINT proto,UINT port,THREAD_PROC * proc,void * thread_param,bool local_only,bool shadow_ipv6,volatile UINT * natt_global_udp_port,UCHAR rand_port_id,bool enable_ca)768 LISTENER *NewListenerEx5(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only, bool shadow_ipv6,
769 						 volatile UINT *natt_global_udp_port, UCHAR rand_port_id, bool enable_ca)
770 {
771 	LISTENER *r;
772 	THREAD *t;
773 	// Validate arguments
774 	if ((proto == LISTENER_TCP && port == 0) || cedar == NULL)
775 	{
776 		return NULL;
777 	}
778 	// Check the protocol number
779 	if (proto != LISTENER_TCP && proto != LISTENER_INPROC &&
780 		proto != LISTENER_RUDP && proto != LISTENER_ICMP && proto != LISTENER_DNS &&
781 		proto != LISTENER_REVERSE)
782 	{
783 		return NULL;
784 	}
785 
786 	r = ZeroMalloc(sizeof(LISTENER));
787 
788 	r->ThreadProc = proc;
789 	r->ThreadParam = thread_param;
790 	r->Cedar = cedar;
791 	AddRef(r->Cedar->ref);
792 	r->lock = NewLock();
793 	r->ref = NewRef();
794 	r->Protocol = proto;
795 	r->Port = port;
796 	r->Event = NewEvent();
797 
798 
799 	r->LocalOnly = local_only;
800 	r->ShadowIPv6 = shadow_ipv6;
801 	r->NatTGlobalUdpPort = natt_global_udp_port;
802 	r->RandPortId = rand_port_id;
803 	r->EnableConditionalAccept = enable_ca;
804 
805 	if (r->ShadowIPv6 == false)
806 	{
807 		if (proto == LISTENER_TCP)
808 		{
809 			SLog(cedar, "LS_LISTENER_START_1", port);
810 		}
811 	}
812 
813 	// Creating a thread
814 	t = NewThread(ListenerThread, r);
815 	WaitThreadInit(t);
816 	ReleaseThread(t);
817 
818 	if (r->ShadowIPv6 == false && proto == LISTENER_TCP)
819 	{
820 		if (r->Cedar->DisableIPv6Listener == false)
821 		{
822 			// Add a shadow listener
823 			r->ShadowListener = NewListenerEx3(cedar, proto, port, proc, thread_param,
824 				local_only, true);
825 		}
826 	}
827 
828 	if (r->ShadowIPv6 == false)
829 	{
830 		// Add to the Cedar
831 		AddListener(cedar, r);
832 	}
833 
834 	return r;
835 }
836 
837 // Get the session from the session key
GetSessionFromUDPEntry(CEDAR * cedar,UINT key32)838 SESSION *GetSessionFromUDPEntry(CEDAR *cedar, UINT key32)
839 {
840 	UDP_ENTRY *e, t;
841 	SESSION *s;
842 	// Validate arguments
843 	if (cedar == NULL)
844 	{
845 		return NULL;
846 	}
847 
848 	t.SessionKey32 = key32;
849 
850 	LockList(cedar->UDPEntryList);
851 	{
852 		e = Search(cedar->UDPEntryList, &t);
853 		if (e == NULL)
854 		{
855 			UnlockList(cedar->UDPEntryList);
856 			return NULL;
857 		}
858 		s = e->Session;
859 		AddRef(s->ref);
860 	}
861 	UnlockList(cedar->UDPEntryList);
862 
863 	return s;
864 }
865 
866 // Delete the UDP session from the UDP entry
DelUDPEntry(CEDAR * cedar,SESSION * session)867 void DelUDPEntry(CEDAR *cedar, SESSION *session)
868 {
869 	UINT num, i;
870 	// Validate arguments
871 	if (cedar == NULL || session == NULL)
872 	{
873 		return;
874 	}
875 
876 	LockList(cedar->UDPEntryList);
877 	{
878 		num = LIST_NUM(cedar->UDPEntryList);
879 		for (i = 0;i < num;i++)
880 		{
881 			UDP_ENTRY *e = LIST_DATA(cedar->UDPEntryList, i);
882 			if (e->Session == session)
883 			{
884 				ReleaseSession(e->Session);
885 				Delete(cedar->UDPEntryList, e);
886 				Free(e);
887 				UnlockList(cedar->UDPEntryList);
888 				Debug("UDP_Entry Deleted.\n");
889 				return;
890 			}
891 		}
892 	}
893 	UnlockList(cedar->UDPEntryList);
894 }
895 
896 // Add an UDP session to the UDP entry
AddUDPEntry(CEDAR * cedar,SESSION * session)897 void AddUDPEntry(CEDAR *cedar, SESSION *session)
898 {
899 	UDP_ENTRY *e;
900 	// Validate arguments
901 	if (cedar == NULL || session == NULL)
902 	{
903 		return;
904 	}
905 
906 	e = ZeroMalloc(sizeof(UDP_ENTRY));
907 	e->Session = session;
908 	e->SessionKey32 = session->SessionKey32;
909 	AddRef(session->ref);
910 
911 	LockList(cedar->UDPEntryList);
912 	{
913 		Add(cedar->UDPEntryList, e);
914 	}
915 	UnlockList(cedar->UDPEntryList);
916 
917 	Debug("UDP_Entry Added.\n");
918 }
919 
920 // Clear the UDP entry
CleanupUDPEntry(CEDAR * cedar)921 void CleanupUDPEntry(CEDAR *cedar)
922 {
923 	// Validate arguments
924 	if (cedar == NULL)
925 	{
926 		return;
927 	}
928 }
929 
930 // Create a new dynamic listener
NewDynamicListener(CEDAR * c,bool * enable_ptr,UINT protocol,UINT port)931 DYNAMIC_LISTENER *NewDynamicListener(CEDAR *c, bool *enable_ptr, UINT protocol, UINT port)
932 {
933 	DYNAMIC_LISTENER *d;
934 	// Validate arguments
935 	if (c == NULL || enable_ptr == NULL)
936 	{
937 		return NULL;
938 	}
939 
940 	d = ZeroMalloc(sizeof(DYNAMIC_LISTENER));
941 
942 	d->Cedar = c;
943 	AddRef(d->Cedar->ref);
944 
945 	d->Lock = NewLock();
946 
947 	d->EnablePtr = enable_ptr;
948 
949 	d->Listener = NULL;
950 
951 	d->Protocol = protocol;
952 	d->Port = port;
953 
954 	ApplyDynamicListener(d);
955 
956 	return d;
957 }
958 
959 // Release the dynamic listener
FreeDynamicListener(DYNAMIC_LISTENER * d)960 void FreeDynamicListener(DYNAMIC_LISTENER *d)
961 {
962 	// Validate arguments
963 	if (d == NULL)
964 	{
965 		return;
966 	}
967 
968 	Lock(d->Lock);
969 	{
970 		if (d->Listener != NULL)
971 		{
972 			StopListener(d->Listener);
973 			ReleaseListener(d->Listener);
974 			d->Listener = NULL;
975 		}
976 	}
977 	Unlock(d->Lock);
978 
979 	ReleaseCedar(d->Cedar);
980 
981 	DeleteLock(d->Lock);
982 
983 	Free(d);
984 }
985 
986 // Set the state to dynamic listener
ApplyDynamicListener(DYNAMIC_LISTENER * d)987 void ApplyDynamicListener(DYNAMIC_LISTENER *d)
988 {
989 	// Validate arguments
990 	if (d == NULL)
991 	{
992 		return;
993 	}
994 
995 	Lock(d->Lock);
996 	{
997 		// Change the state
998 		if (*d->EnablePtr)
999 		{
1000 			if (d->Listener == NULL)
1001 			{
1002 				// Create a listener
1003 				WHERE;
1004 				d->Listener = NewListener(d->Cedar, d->Protocol, d->Port);
1005 			}
1006 		}
1007 		else
1008 		{
1009 			// Stop the listener
1010 			if (d->Listener != NULL)
1011 			{
1012 				WHERE;
1013 				StopListener(d->Listener);
1014 				ReleaseListener(d->Listener);
1015 				d->Listener = NULL;
1016 			}
1017 		}
1018 	}
1019 	Unlock(d->Lock);
1020 }
1021 
1022 
1023