1 // SoftEther VPN Source Code - Stable Edition Repository
2 // Cedar Communication Module
3 //
4 // SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
5 //
6 // Copyright (c) Daiyuu Nobori.
7 // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
8 // Copyright (c) SoftEther Corporation.
9 // Copyright (c) all contributors on SoftEther VPN project in GitHub.
10 //
11 // All Rights Reserved.
12 //
13 // http://www.softether.org/
14 //
15 // This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
16 // Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
17 //
18 // License: The Apache License, Version 2.0
19 // https://www.apache.org/licenses/LICENSE-2.0
20 //
21 // DISCLAIMER
22 // ==========
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 // SOFTWARE.
31 //
32 // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
33 // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
34 // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
35 // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
36 // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
37 // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
38 // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
39 // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
40 // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
41 // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
42 // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
43 // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
44 // LAW OR COURT RULE.
45 //
46 // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE
47 // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL
48 // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS
49 // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND
50 // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING
51 // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER
52 // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES.
53 // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
54 // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES
55 // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH
56 // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS
57 // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE
58 // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A
59 // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE
60 // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
61 // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A
62 // STATEMENT FOR WARNING AND DISCLAIMER.
63 //
64 // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE.
65 // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH
66 // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE.
67 //
68 //
69 // SOURCE CODE CONTRIBUTION
70 // ------------------------
71 //
72 // Your contribution to SoftEther VPN Project is much appreciated.
73 // Please send patches to us through GitHub.
74 // Read the SoftEther VPN Patch Acceptance Policy in advance:
75 // http://www.softether.org/5-download/src/9.patch
76 //
77 //
78 // DEAR SECURITY EXPERTS
79 // ---------------------
80 //
81 // If you find a bug or a security vulnerability please kindly inform us
82 // about the problem immediately so that we can fix the security problem
83 // to protect a lot of users around the world as soon as possible.
84 //
85 // Our e-mail address for security reports is:
86 // softether-vpn-security [at] softether.org
87 //
88 // Please note that the above e-mail address is not a technical support
89 // inquiry address. If you need technical assistance, please visit
90 // http://www.softether.org/ and ask your question on the users forum.
91 //
92 // Thank you for your cooperation.
93 //
94 //
95 // NO MEMORY OR RESOURCE LEAKS
96 // ---------------------------
97 //
98 // The memory-leaks and resource-leaks verification under the stress
99 // test has been passed before release this source code.
100 
101 
102 // Listener.c
103 // Listener module
104 
105 #include "CedarPch.h"
106 
107 static bool disable_dos = false;
108 static UINT max_connections_per_ip = DEFAULT_MAX_CONNECTIONS_PER_IP;
109 static UINT max_unestablished_connections = DEFAULT_MAX_UNESTABLISHED_CONNECTIONS;
110 static bool listener_proc_recv_rpc = false;
111 
112 // Set the flag of whether to response to the RPC of RUDP
ListenerSetProcRecvRpcEnable(bool b)113 void ListenerSetProcRecvRpcEnable(bool b)
114 {
115 	listener_proc_recv_rpc = b;
116 }
117 
118 // Get the number of allowed outstanding connections
GetMaxUnestablishedConnections()119 UINT GetMaxUnestablishedConnections()
120 {
121 	return max_unestablished_connections;
122 }
123 
124 // Set the number of allowed outstanding connections
SetMaxUnestablishedConnections(UINT num)125 void SetMaxUnestablishedConnections(UINT num)
126 {
127 	if (num == 0)
128 	{
129 		num = DEFAULT_MAX_UNESTABLISHED_CONNECTIONS;
130 	}
131 
132 	max_unestablished_connections = MAX(num, max_connections_per_ip);
133 }
134 
135 // Get the maximum number of connections per IP address
GetMaxConnectionsPerIp()136 UINT GetMaxConnectionsPerIp()
137 {
138 	return max_connections_per_ip;
139 }
140 
141 // Set the maximum number of connections per IP address
SetMaxConnectionsPerIp(UINT num)142 void SetMaxConnectionsPerIp(UINT num)
143 {
144 	if (num == 0)
145 	{
146 		num = DEFAULT_MAX_CONNECTIONS_PER_IP;
147 	}
148 	max_connections_per_ip = MAX(num, MIN_MAX_CONNECTIONS_PER_IP);
149 }
150 
151 // Enable the DoS defense
EnableDosProtect()152 void EnableDosProtect()
153 {
154 	disable_dos = false;
155 }
156 
157 // Disable the DoS defense
DisableDosProtect()158 void DisableDosProtect()
159 {
160 	disable_dos = true;
161 }
162 
163 // An UDP packet has been received
UDPReceivedPacket(CEDAR * cedar,SOCK * s,IP * ip,UINT port,void * data,UINT size)164 void UDPReceivedPacket(CEDAR *cedar, SOCK *s, IP *ip, UINT port, void *data, UINT size)
165 {
166 	SESSION *session;
167 	UINT *key32;
168 	UCHAR *buf;
169 	CONNECTION *c;
170 	// Validate arguments
171 	if (s == NULL || ip == NULL || data == NULL || size == 0 || cedar == NULL)
172 	{
173 		return;
174 	}
175 
176 	if (size < 16)
177 	{
178 		// Ignore since the packet size is not enough
179 		return;
180 	}
181 	buf = (UCHAR *)data;
182 	key32 = (UINT *)(buf + 4);
183 
184 
185 	// Get the session from the Key32 value
186 	session = GetSessionFromUDPEntry(cedar, Endian32(*key32));
187 	if (session == NULL)
188 	{
189 		Debug("Invalid UDP Session Key 32: 0x%X\n", *key32);
190 		return;
191 	}
192 
193 	c = session->Connection;
194 
195 	// Write the data
196 	PutUDPPacketData(c, buf, size);
197 
198 	// Rewrite the UDP socket associated with the connection
199 	Lock(c->lock);
200 	{
201 		if (c->Protocol == CONNECTION_UDP)
202 		{
203 			if (c->Udp->s != s)
204 			{
205 				if (c->Udp->s != NULL)
206 				{
207 					ReleaseSock(c->Udp->s);
208 				}
209 				AddRef(s->ref);
210 				c->Udp->s = s;
211 			}
212 			Copy(&c->Udp->ip, ip, sizeof(UINT));
213 			c->Udp->port = port;
214 		}
215 	}
216 	Unlock(c->lock);
217 
218 	// Invoke the Cancel
219 	Cancel(session->Cancel1);
220 
221 	// Release the session
222 	ReleaseSession(session);
223 }
224 
225 // Thread that processes the accepted TCP connection
TCPAcceptedThread(THREAD * t,void * param)226 void TCPAcceptedThread(THREAD *t, void *param)
227 {
228 	TCP_ACCEPTED_PARAM *data;
229 	LISTENER *r;
230 	SOCK *s;
231 	CONNECTION *c;
232 	bool flag1;
233 	char tmp[128];
234 	// Validate arguments
235 	if (t == NULL || param == NULL)
236 	{
237 		return;
238 	}
239 
240 	// Initialize
241 	data = (TCP_ACCEPTED_PARAM *)param;
242 	r = data->r;
243 	s = data->s;
244 	AddRef(r->ref);
245 	AddRef(s->ref);
246 
247 	// Create a connection
248 	c = NewServerConnection(r->Cedar, s, t);
249 
250 	AddRef(r->ref);
251 	c->Listener = r;
252 
253 	// Register to Cedar as a transient connection
254 	AddConnection(c->Cedar, c);
255 
256 	NoticeThreadInit(t);
257 
258 	AcceptInit(s);
259 	StrCpy(c->ClientHostname, sizeof(c->ClientHostname), s->RemoteHostname);
260 	IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
261 	if (IS_SPECIAL_PORT(s->RemotePort) == false)
262 	{
263 		SLog(r->Cedar, "LS_LISTENER_ACCEPT", r->Port, tmp, s->RemoteHostname, s->RemotePort);
264 	}
265 
266 	// Reception
267 	ConnectionAccept(c);
268 	flag1 = c->flag1;
269 
270 
271 	// Release
272 	SLog(r->Cedar, "LS_CONNECTION_END_1", c->Name);
273 	ReleaseListener(c->Listener);
274 	c->Listener = NULL;
275 	ReleaseConnection(c);
276 
277 	// Release
278 	if (flag1 == false)
279 	{
280 		Debug("%s %u flag1 == false\n", __FILE__, __LINE__);
281 		IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
282 
283 		if (IS_SPECIAL_PORT(s->RemotePort) == false)
284 		{
285 			SLog(r->Cedar, "LS_LISTENER_DISCONNECT", tmp, s->RemotePort);
286 		}
287 		Disconnect(s);
288 	}
289 	ReleaseSock(s);
290 	ReleaseListener(r);
291 }
292 
293 // Jump here if there is accepted connection in the TCP
TCPAccepted(LISTENER * r,SOCK * s)294 void TCPAccepted(LISTENER *r, SOCK *s)
295 {
296 	TCP_ACCEPTED_PARAM *data;
297 	THREAD *t;
298 	char tmp[MAX_SIZE];
299 	UINT num_clients_from_this_ip = 0;
300 	CEDAR *cedar;
301 	// Validate arguments
302 	if (r == NULL || s == NULL)
303 	{
304 		return;
305 	}
306 
307 	cedar = r->Cedar;
308 
309 	num_clients_from_this_ip = GetNumIpClient(&s->RemoteIP);
310 
311 
312 	IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
313 
314 	data = ZeroMalloc(sizeof(TCP_ACCEPTED_PARAM));
315 	data->r = r;
316 	data->s = s;
317 
318 	if (r->ThreadProc == TCPAcceptedThread)
319 	{
320 		Inc(cedar->AcceptingSockets);
321 	}
322 
323 	t = NewThread(r->ThreadProc, data);
324 	WaitThreadInit(t);
325 	Free(data);
326 	ReleaseThread(t);
327 }
328 
329 
330 // UDP listener main loop
ListenerUDPMainLoop(LISTENER * r)331 void ListenerUDPMainLoop(LISTENER *r)
332 {
333 	UCHAR *data;
334 	// Validate arguments
335 	if (r == NULL)
336 	{
337 		return;
338 	}
339 
340 	Debug("ListenerUDPMainLoop Starts.\n");
341 	r->Status = LISTENER_STATUS_TRYING;
342 
343 	while (true)
344 	{
345 		// Try to listen on the UDP port
346 		while (true)
347 		{
348 			// Stop flag inspection
349 			if (r->Halt)
350 			{
351 				// Stop
352 				return;
353 			}
354 
355 			Debug("NewUDP()\n");
356 			r->Sock = NewUDP(r->Port);
357 			if (r->Sock != NULL)
358 			{
359 				// Wait success
360 				break;
361 			}
362 
363 			// Wait failure
364 			Debug("Failed to NewUDP.\n");
365 			Wait(r->Event, LISTEN_RETRY_TIME);
366 
367 			// Stop flag inspection
368 			if (r->Halt)
369 			{
370 				Debug("UDP Halt.\n");
371 				return;
372 			}
373 		}
374 
375 		r->Status = LISTENER_STATUS_LISTENING;
376 		Debug("Start Listening at UDP Port %u.\n", r->Sock->LocalPort);
377 
378 		// Stop flag inspection
379 		if (r->Halt)
380 		{
381 			// Stop
382 			goto STOP;
383 		}
384 
385 		// Allocate the buffer area
386 		data = Malloc(UDP_PACKET_SIZE);
387 
388 		// Read the next packet
389 		while (true)
390 		{
391 			IP src_ip;
392 			UINT src_port;
393 			UINT size;
394 			SOCKSET set;
395 
396 			InitSockSet(&set);
397 			AddSockSet(&set, r->Sock);
398 			Select(&set, SELECT_TIME, NULL, NULL);
399 
400 			size = RecvFrom(r->Sock, &src_ip, &src_port, data, UDP_PACKET_SIZE);
401 			if (((size == 0) && (r->Sock->IgnoreRecvErr == false)) || r->Halt)
402 			{
403 				// Error has occurred
404 STOP:
405 				Disconnect(r->Sock);
406 				ReleaseSock(r->Sock);
407 				r->Sock = NULL;
408 				Debug("UDP Listen Stopped.\n");
409 				Free(data);
410 				break;
411 			}
412 
413 			// Received an UDP packet
414 			if (size != SOCK_LATER)
415 			{
416 				UDPReceivedPacket(r->Cedar, r->Sock, &src_ip, src_port, data, size);
417 			}
418 		}
419 	}
420 }
421 
422 // RPC reception procedure
ListenerRUDPRpcRecvProc(RUDP_STACK * r,UDPPACKET * p)423 bool ListenerRUDPRpcRecvProc(RUDP_STACK *r, UDPPACKET *p)
424 {
425 	return false;
426 }
427 
428 // TCP listener main loop
ListenerTCPMainLoop(LISTENER * r)429 void ListenerTCPMainLoop(LISTENER *r)
430 {
431 	SOCK *new_sock;
432 	SOCK *s;
433 	// Validate arguments
434 	if (r == NULL)
435 	{
436 		return;
437 	}
438 
439 	Debug("ListenerTCPMainLoop Starts.\n");
440 	r->Status = LISTENER_STATUS_TRYING;
441 
442 	while (true)
443 	{
444 		bool first_failed = true;
445 		Debug("Status = LISTENER_STATUS_TRYING\n");
446 		r->Status = LISTENER_STATUS_TRYING;
447 
448 		// Try to Listen
449 		while (true)
450 		{
451 			UINT interval;
452 			// Stop flag inspection
453 			if (r->Halt)
454 			{
455 				// Stop
456 				return;
457 			}
458 
459 			s = NULL;
460 
461 			if (r->Protocol == LISTENER_TCP)
462 			{
463 				if (r->ShadowIPv6 == false)
464 				{
465 					s = ListenEx2(r->Port, r->LocalOnly, r->EnableConditionalAccept);
466 				}
467 				else
468 				{
469 					s = ListenEx6(r->Port, r->LocalOnly);
470 				}
471 			}
472 			else if (r->Protocol == LISTENER_INPROC)
473 			{
474 				s = ListenInProc();
475 			}
476 			else if (r->Protocol == LISTENER_RUDP)
477 			{
478 				s = ListenRUDPEx(VPN_RUDP_SVC_NAME, NULL, ListenerRUDPRpcRecvProc, NULL, 0, false, false, r->NatTGlobalUdpPort, r->RandPortId);
479 			}
480 			else if (r->Protocol == LISTENER_ICMP)
481 			{
482 				s = ListenRUDP(VPN_RUDP_SVC_NAME, NULL, ListenerRUDPRpcRecvProc, NULL, MAKE_SPECIAL_PORT(IP_PROTO_ICMPV4),
483 					true, false);
484 			}
485 			else if (r->Protocol == LISTENER_DNS)
486 			{
487 				s = ListenRUDP(VPN_RUDP_SVC_NAME, NULL, ListenerRUDPRpcRecvProc, NULL, 53, true, true);
488 			}
489 			else if (r->Protocol == LISTENER_REVERSE)
490 			{
491 				s = ListenReverse();
492 			}
493 
494 			if (s != NULL)
495 			{
496 				// Listen success
497 				AddRef(s->ref);
498 
499 				Lock(r->lock);
500 				{
501 					r->Sock = s;
502 				}
503 				Unlock(r->lock);
504 
505 				if (r->ShadowIPv6 == false && r->Protocol == LISTENER_TCP)
506 				{
507 					SLog(r->Cedar, "LS_LISTENER_START_2", r->Port);
508 				}
509 				break;
510 			}
511 
512 			// Listen failure
513 			if (first_failed)
514 			{
515 				first_failed = false;
516 				if (r->ShadowIPv6 == false && r->Protocol == LISTENER_TCP)
517 				{
518 					SLog(r->Cedar, "LS_LISTENER_START_3", r->Port, LISTEN_RETRY_TIME / 1000);
519 				}
520 			}
521 
522 			interval = LISTEN_RETRY_TIME;
523 
524 			if (r->ShadowIPv6)
525 			{
526 				if (IsIPv6Supported() == false)
527 				{
528 					interval = LISTEN_RETRY_TIME_NOIPV6;
529 
530 					Debug("IPv6 is not supported.\n");
531 				}
532 			}
533 
534 			Wait(r->Event, interval);
535 
536 			// Stop flag inspection
537 			if (r->Halt)
538 			{
539 				// Stop
540 				Debug("Listener Halt.\n");
541 				return;
542 			}
543 		}
544 
545 		r->Status = LISTENER_STATUS_LISTENING;
546 		Debug("Status = LISTENER_STATUS_LISTENING\n");
547 
548 		// Stop flag inspection
549 		if (r->Halt)
550 		{
551 			// Stop
552 			goto STOP;
553 		}
554 
555 		// Accpet loop
556 		while (true)
557 		{
558 			// Accept
559 			Debug("Accept()\n");
560 			new_sock = Accept(s);
561 			if (new_sock != NULL)
562 			{
563 				// Accept success
564 				Debug("Accepted.\n");
565 				TCPAccepted(r, new_sock);
566 				ReleaseSock(new_sock);
567 			}
568 			else
569 			{
570 STOP:
571 				Debug("Accept Canceled.\n");
572 				// Failed to accept (socket is destroyed)
573 				// Close the listening socket
574 				Disconnect(s);
575 				ReleaseSock(s);
576 				s = NULL;
577 
578 				Lock(r->lock);
579 				{
580 					if (r->Sock != NULL)
581 					{
582 						s = r->Sock;
583 						r->Sock = NULL;
584 					}
585 				}
586 				Unlock(r->lock);
587 
588 				if (s != NULL)
589 				{
590 					ReleaseSock(s);
591 				}
592 
593 				s = NULL;
594 
595 				break;
596 			}
597 		}
598 
599 		// Stop flag inspection
600 		if (r->Halt)
601 		{
602 			// Stop
603 			Debug("Listener Halt.\n");
604 			return;
605 		}
606 	}
607 }
608 
609 //  Listener Thread
ListenerThread(THREAD * thread,void * param)610 void ListenerThread(THREAD *thread, void *param)
611 {
612 	LISTENER *r;
613 	// Validate arguments
614 	if (thread == NULL || param == NULL)
615 	{
616 		return;
617 	}
618 
619 	// Initialize
620 	r = (LISTENER *)param;
621 	AddRef(r->ref);
622 	r->Thread = thread;
623 	AddRef(thread->ref);
624 	NoticeThreadInit(thread);
625 
626 	// Main loop
627 	switch (r->Protocol)
628 	{
629 	case LISTENER_TCP:
630 	case LISTENER_INPROC:
631 	case LISTENER_RUDP:
632 	case LISTENER_DNS:
633 	case LISTENER_ICMP:
634 	case LISTENER_REVERSE:
635 		// TCP or other stream-based protocol
636 		ListenerTCPMainLoop(r);
637 		break;
638 
639 	case LISTENER_UDP:
640 		// UDP protocol
641 		ListenerUDPMainLoop(r);
642 		break;
643 	}
644 
645 	// Release
646 	ReleaseListener(r);
647 }
648 
649 // Shutdown the Listener
StopListener(LISTENER * r)650 void StopListener(LISTENER *r)
651 {
652 	UINT port;
653 	SOCK *s = NULL;
654 	// Validate arguments
655 	if (r == NULL)
656 	{
657 		return;
658 	}
659 
660 	Lock(r->lock);
661 	if (r->Halt)
662 	{
663 		Unlock(r->lock);
664 		return;
665 	}
666 
667 	// Stop flag set
668 	r->Halt = true;
669 
670 	if (r->Sock != NULL)
671 	{
672 		s = r->Sock;
673 
674 		AddRef(s->ref);
675 	}
676 
677 	Unlock(r->lock);
678 
679 	port = r->Port;
680 
681 	if (r->ShadowIPv6 == false && r->Protocol == LISTENER_TCP)
682 	{
683 		SLog(r->Cedar, "LS_LISTENER_STOP_1", port);
684 	}
685 
686 	// Close the socket
687 	if (s != NULL)
688 	{
689 		Disconnect(s);
690 		ReleaseSock(s);
691 		s = NULL;
692 	}
693 
694 	// Set the event
695 	Set(r->Event);
696 
697 	// Wait for stopping the thread
698 	WaitThread(r->Thread, INFINITE);
699 
700 	// Stop the shadow listener
701 	if (r->ShadowIPv6 == false)
702 	{
703 		if (r->ShadowListener != NULL)
704 		{
705 			StopListener(r->ShadowListener);
706 
707 			ReleaseListener(r->ShadowListener);
708 
709 			r->ShadowListener = NULL;
710 		}
711 	}
712 
713 	if (r->ShadowIPv6 == false && r->Protocol == LISTENER_TCP)
714 	{
715 		SLog(r->Cedar, "LS_LISTENER_STOP_2", port);
716 	}
717 }
718 
719 // Cleanup the listener
CleanupListener(LISTENER * r)720 void CleanupListener(LISTENER *r)
721 {
722 	UINT i = 0;
723 	// Validate arguments
724 	if (r == NULL)
725 	{
726 		return;
727 	}
728 
729 
730 	if (r->Sock != NULL)
731 	{
732 		ReleaseSock(r->Sock);
733 	}
734 
735 	DeleteLock(r->lock);
736 	ReleaseThread(r->Thread);
737 	ReleaseEvent(r->Event);
738 
739 	ReleaseCedar(r->Cedar);
740 
741 	Free(r);
742 }
743 
744 // Release the listener
ReleaseListener(LISTENER * r)745 void ReleaseListener(LISTENER *r)
746 {
747 	// Validate arguments
748 	if (r == NULL)
749 	{
750 		return;
751 	}
752 
753 	if (Release(r->ref) == 0)
754 	{
755 		CleanupListener(r);
756 	}
757 }
758 
759 // Comparison function of UDP entry list
CompareUDPEntry(void * p1,void * p2)760 int CompareUDPEntry(void *p1, void *p2)
761 {
762 	UDP_ENTRY *e1, *e2;
763 	if (p1 == NULL || p2 == NULL)
764 	{
765 		return 0;
766 	}
767 	e1 = *(UDP_ENTRY **)p1;
768 	e2 = *(UDP_ENTRY **)p2;
769 	if (e1 == NULL || e2 == NULL)
770 	{
771 		return 0;
772 	}
773 
774 	if (e1->SessionKey32 > e2->SessionKey32)
775 	{
776 		return 1;
777 	}
778 	else if (e1->SessionKey32 == e2->SessionKey32)
779 	{
780 		return 0;
781 	}
782 	else
783 	{
784 		return -1;
785 	}
786 }
787 
788 // Comparison function of the listener
CompareListener(void * p1,void * p2)789 int CompareListener(void *p1, void *p2)
790 {
791 	LISTENER *r1, *r2;
792 	if (p1 == NULL || p2 == NULL)
793 	{
794 		return 0;
795 	}
796 	r1 = *(LISTENER **)p1;
797 	r2 = *(LISTENER **)p2;
798 	if (r1 == NULL || r2 == NULL)
799 	{
800 		return 0;
801 	}
802 
803 	if (r1->Protocol > r2->Protocol)
804 	{
805 		return 1;
806 	}
807 	else if (r1->Protocol < r2->Protocol)
808 	{
809 		return -1;
810 	}
811 	else if (r1->Port > r2->Port)
812 	{
813 		return 1;
814 	}
815 	else if (r1->Port < r2->Port)
816 	{
817 		return -1;
818 	}
819 	else
820 	{
821 		return 0;
822 	}
823 }
824 
825 // Create a New Listener
NewListener(CEDAR * cedar,UINT proto,UINT port)826 LISTENER *NewListener(CEDAR *cedar, UINT proto, UINT port)
827 {
828 	return NewListenerEx(cedar, proto, port, TCPAcceptedThread, NULL);
829 }
NewListenerEx(CEDAR * cedar,UINT proto,UINT port,THREAD_PROC * proc,void * thread_param)830 LISTENER *NewListenerEx(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param)
831 {
832 	return NewListenerEx2(cedar, proto, port, proc, thread_param, false);
833 }
NewListenerEx2(CEDAR * cedar,UINT proto,UINT port,THREAD_PROC * proc,void * thread_param,bool local_only)834 LISTENER *NewListenerEx2(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only)
835 {
836 	return NewListenerEx3(cedar, proto, port, proc, thread_param, local_only, false);
837 }
NewListenerEx3(CEDAR * cedar,UINT proto,UINT port,THREAD_PROC * proc,void * thread_param,bool local_only,bool shadow_ipv6)838 LISTENER *NewListenerEx3(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only, bool shadow_ipv6)
839 {
840 	return NewListenerEx4(cedar, proto, port, proc, thread_param, local_only, shadow_ipv6, NULL, 0);
841 }
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)842 LISTENER *NewListenerEx4(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only, bool shadow_ipv6,
843 						 volatile UINT *natt_global_udp_port, UCHAR rand_port_id)
844 {
845 	return NewListenerEx5(cedar, proto, port, proc, thread_param,
846 		local_only, shadow_ipv6, natt_global_udp_port, rand_port_id, false);
847 }
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)848 LISTENER *NewListenerEx5(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only, bool shadow_ipv6,
849 						 volatile UINT *natt_global_udp_port, UCHAR rand_port_id, bool enable_ca)
850 {
851 	LISTENER *r;
852 	THREAD *t;
853 	// Validate arguments
854 	if ((proto == LISTENER_TCP && port == 0) || cedar == NULL)
855 	{
856 		return NULL;
857 	}
858 	// Check the protocol number
859 	if (proto != LISTENER_TCP && proto != LISTENER_INPROC &&
860 		proto != LISTENER_RUDP && proto != LISTENER_ICMP && proto != LISTENER_DNS &&
861 		proto != LISTENER_REVERSE)
862 	{
863 		return NULL;
864 	}
865 
866 	r = ZeroMalloc(sizeof(LISTENER));
867 
868 	r->ThreadProc = proc;
869 	r->ThreadParam = thread_param;
870 	r->Cedar = cedar;
871 	AddRef(r->Cedar->ref);
872 	r->lock = NewLock();
873 	r->ref = NewRef();
874 	r->Protocol = proto;
875 	r->Port = port;
876 	r->Event = NewEvent();
877 
878 
879 	r->LocalOnly = local_only;
880 	r->ShadowIPv6 = shadow_ipv6;
881 	r->NatTGlobalUdpPort = natt_global_udp_port;
882 	r->RandPortId = rand_port_id;
883 	r->EnableConditionalAccept = enable_ca;
884 
885 	if (r->ShadowIPv6 == false)
886 	{
887 		if (proto == LISTENER_TCP)
888 		{
889 			SLog(cedar, "LS_LISTENER_START_1", port);
890 		}
891 	}
892 
893 	// Creating a thread
894 	t = NewThread(ListenerThread, r);
895 	WaitThreadInit(t);
896 	ReleaseThread(t);
897 
898 	if (r->ShadowIPv6 == false && proto == LISTENER_TCP)
899 	{
900 		if (r->Cedar->DisableIPv6Listener == false)
901 		{
902 			// Add a shadow listener
903 			r->ShadowListener = NewListenerEx3(cedar, proto, port, proc, thread_param,
904 				local_only, true);
905 		}
906 	}
907 
908 	if (r->ShadowIPv6 == false)
909 	{
910 		// Add to the Cedar
911 		AddListener(cedar, r);
912 	}
913 
914 	return r;
915 }
916 
917 // Get the session from the session key
GetSessionFromUDPEntry(CEDAR * cedar,UINT key32)918 SESSION *GetSessionFromUDPEntry(CEDAR *cedar, UINT key32)
919 {
920 	UDP_ENTRY *e, t;
921 	SESSION *s;
922 	// Validate arguments
923 	if (cedar == NULL)
924 	{
925 		return NULL;
926 	}
927 
928 	t.SessionKey32 = key32;
929 
930 	LockList(cedar->UDPEntryList);
931 	{
932 		e = Search(cedar->UDPEntryList, &t);
933 		if (e == NULL)
934 		{
935 			UnlockList(cedar->UDPEntryList);
936 			return NULL;
937 		}
938 		s = e->Session;
939 		AddRef(s->ref);
940 	}
941 	UnlockList(cedar->UDPEntryList);
942 
943 	return s;
944 }
945 
946 // Delete the UDP session from the UDP entry
DelUDPEntry(CEDAR * cedar,SESSION * session)947 void DelUDPEntry(CEDAR *cedar, SESSION *session)
948 {
949 	UINT num, i;
950 	// Validate arguments
951 	if (cedar == NULL || session == NULL)
952 	{
953 		return;
954 	}
955 
956 	LockList(cedar->UDPEntryList);
957 	{
958 		num = LIST_NUM(cedar->UDPEntryList);
959 		for (i = 0;i < num;i++)
960 		{
961 			UDP_ENTRY *e = LIST_DATA(cedar->UDPEntryList, i);
962 			if (e->Session == session)
963 			{
964 				ReleaseSession(e->Session);
965 				Delete(cedar->UDPEntryList, e);
966 				Free(e);
967 				UnlockList(cedar->UDPEntryList);
968 				Debug("UDP_Entry Deleted.\n");
969 				return;
970 			}
971 		}
972 	}
973 	UnlockList(cedar->UDPEntryList);
974 }
975 
976 // Add an UDP session to the UDP entry
AddUDPEntry(CEDAR * cedar,SESSION * session)977 void AddUDPEntry(CEDAR *cedar, SESSION *session)
978 {
979 	UDP_ENTRY *e;
980 	// Validate arguments
981 	if (cedar == NULL || session == NULL)
982 	{
983 		return;
984 	}
985 
986 	e = ZeroMalloc(sizeof(UDP_ENTRY));
987 	e->Session = session;
988 	e->SessionKey32 = session->SessionKey32;
989 	AddRef(session->ref);
990 
991 	LockList(cedar->UDPEntryList);
992 	{
993 		Add(cedar->UDPEntryList, e);
994 	}
995 	UnlockList(cedar->UDPEntryList);
996 
997 	Debug("UDP_Entry Added.\n");
998 }
999 
1000 // Clear the UDP entry
CleanupUDPEntry(CEDAR * cedar)1001 void CleanupUDPEntry(CEDAR *cedar)
1002 {
1003 	// Validate arguments
1004 	if (cedar == NULL)
1005 	{
1006 		return;
1007 	}
1008 }
1009 
1010 // Create a new dynamic listener
NewDynamicListener(CEDAR * c,bool * enable_ptr,UINT protocol,UINT port)1011 DYNAMIC_LISTENER *NewDynamicListener(CEDAR *c, bool *enable_ptr, UINT protocol, UINT port)
1012 {
1013 	DYNAMIC_LISTENER *d;
1014 	// Validate arguments
1015 	if (c == NULL || enable_ptr == NULL)
1016 	{
1017 		return NULL;
1018 	}
1019 
1020 	d = ZeroMalloc(sizeof(DYNAMIC_LISTENER));
1021 
1022 	d->Cedar = c;
1023 	AddRef(d->Cedar->ref);
1024 
1025 	d->Lock = NewLock();
1026 
1027 	d->EnablePtr = enable_ptr;
1028 
1029 	d->Listener = NULL;
1030 
1031 	d->Protocol = protocol;
1032 	d->Port = port;
1033 
1034 	ApplyDynamicListener(d);
1035 
1036 	return d;
1037 }
1038 
1039 // Release the dynamic listener
FreeDynamicListener(DYNAMIC_LISTENER * d)1040 void FreeDynamicListener(DYNAMIC_LISTENER *d)
1041 {
1042 	// Validate arguments
1043 	if (d == NULL)
1044 	{
1045 		return;
1046 	}
1047 
1048 	Lock(d->Lock);
1049 	{
1050 		if (d->Listener != NULL)
1051 		{
1052 			StopListener(d->Listener);
1053 			ReleaseListener(d->Listener);
1054 			d->Listener = NULL;
1055 		}
1056 	}
1057 	Unlock(d->Lock);
1058 
1059 	ReleaseCedar(d->Cedar);
1060 
1061 	DeleteLock(d->Lock);
1062 
1063 	Free(d);
1064 }
1065 
1066 // Set the state to dynamic listener
ApplyDynamicListener(DYNAMIC_LISTENER * d)1067 void ApplyDynamicListener(DYNAMIC_LISTENER *d)
1068 {
1069 	// Validate arguments
1070 	if (d == NULL)
1071 	{
1072 		return;
1073 	}
1074 
1075 	Lock(d->Lock);
1076 	{
1077 		// Change the state
1078 		if (*d->EnablePtr)
1079 		{
1080 			if (d->Listener == NULL)
1081 			{
1082 				// Create a listener
1083 				WHERE;
1084 				d->Listener = NewListener(d->Cedar, d->Protocol, d->Port);
1085 			}
1086 		}
1087 		else
1088 		{
1089 			// Stop the listener
1090 			if (d->Listener != NULL)
1091 			{
1092 				WHERE;
1093 				StopListener(d->Listener);
1094 				ReleaseListener(d->Listener);
1095 				d->Listener = NULL;
1096 			}
1097 		}
1098 	}
1099 	Unlock(d->Lock);
1100 }
1101 
1102 
1103