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