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