1 // SoftEther UT-VPN SourceCode
\r
3 // Copyright (C) 2004-2010 SoftEther Corporation.
\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.
\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.
\r
6 // All Rights Reserved.
\r
8 // http://utvpn.tsukuba.ac.jp/
\r
10 // This program is free software; you can redistribute it and/or
\r
11 // modify it under the terms of the GNU General Public License
\r
12 // version 2 as published by the Free Software Foundation.
\r
14 // This program is distributed in the hope that it will be useful,
\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 // GNU General Public License for more details.
\r
19 // You should have received a copy of the GNU General Public License version 2
\r
20 // along with this program; if not, write to the Free Software
\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。
\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の
\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
\r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
\r
34 // および、試験または研究のために利用が行われることを想定して配布
\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
\r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
\r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。
\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
\r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の
\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
\r
58 // 公益保護にご協力いただきますようお願い申し上げます。
\r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
\r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
\r
65 // 日本国内の脆弱性情報届出受付公的機関:
\r
67 // http://www.ipa.go.jp/security/vuln/report/
\r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/
\r
72 // -----------------------------------------------
\r
75 // 新規リリース by SoftEther
\r
76 // -----------------------------------------------
\r
81 #include "CedarPch.h"
\r
83 // UDP パケットを 1 つ受信した
\r
84 void UDPReceivedPacket(CEDAR *cedar, SOCK *s, IP *ip, UINT port, void *data, UINT size)
\r
91 if (s == NULL || ip == NULL || data == NULL || size == 0 || cedar == NULL)
\r
101 buf = (UCHAR *)data;
\r
102 key32 = (UINT *)(buf + 4);
\r
105 // Key32 の値からセッションを取得
\r
106 session = GetSessionFromUDPEntry(cedar, Endian32(*key32));
\r
107 if (session == NULL)
\r
109 Debug("Invalid UDP Session Key 32: 0x%X\n", *key32);
\r
113 c = session->Connection;
\r
116 PutUDPPacketData(c, buf, size);
\r
118 // コネクションに関連付けられている UDP ソケットを書き換える
\r
121 if (c->Protocol == CONNECTION_UDP)
\r
123 if (c->Udp->s != s)
\r
125 if (c->Udp->s != NULL)
\r
127 ReleaseSock(c->Udp->s);
\r
132 Copy(&c->Udp->ip, ip, sizeof(UINT));
\r
133 c->Udp->port = port;
\r
139 Cancel(session->Cancel1);
\r
142 ReleaseSession(session);
\r
145 // Accept された TCP コネクションを処理するスレッド
\r
146 void TCPAcceptedThread(THREAD *t, void *param)
\r
148 TCP_ACCEPTED_PARAM *data;
\r
155 if (t == NULL || param == NULL)
\r
161 data = (TCP_ACCEPTED_PARAM *)param;
\r
168 c = NewServerConnection(r->Cedar, s, t);
\r
170 // Cedar に一時コネクションとして登録する
\r
171 AddConnection(c->Cedar, c);
\r
173 NoticeThreadInit(t);
\r
176 StrCpy(c->ClientHostname, sizeof(c->ClientHostname), s->RemoteHostname);
\r
177 IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
\r
178 SLog(r->Cedar, "LS_LISTENER_ACCEPT", r->Port, tmp, s->RemoteHostname, s->RemotePort);
\r
181 ConnectionAccept(c);
\r
185 SLog(r->Cedar, "LS_CONNECTION_END_1", c->Name);
\r
186 ReleaseConnection(c);
\r
189 if (flag1 == false)
\r
191 Debug("%s %u flag1 == false\n", __FILE__, __LINE__);
\r
192 IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
\r
193 SLog(r->Cedar, "LS_LISTENER_DISCONNECT", tmp, s->RemotePort);
\r
197 ReleaseListener(r);
\r
200 // TCP で Accept されたコネクションがある場合はここに飛ぶ
\r
201 void TCPAccepted(LISTENER *r, SOCK *s)
\r
203 TCP_ACCEPTED_PARAM *data;
\r
205 char tmp[MAX_SIZE];
\r
206 UINT num_clients_from_this_ip = 0;
\r
209 if (r == NULL || s == NULL)
\r
216 num_clients_from_this_ip = GetNumIpClient(&s->RemoteIP);
\r
218 IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
\r
220 data = ZeroMalloc(sizeof(TCP_ACCEPTED_PARAM));
\r
224 if (r->ThreadProc == TCPAcceptedThread)
\r
226 Inc(cedar->AcceptingSockets);
\r
229 t = NewThread(r->ThreadProc, data);
\r
236 void ListenerUDPMainLoop(LISTENER *r)
\r
245 Debug("ListenerUDPMainLoop Starts.\n");
\r
246 r->Status = LISTENER_STATUS_TRYING;
\r
260 Debug("NewUDP()\n");
\r
261 r->Sock = NewUDP(r->Port);
\r
262 if (r->Sock != NULL)
\r
269 Debug("Failed to NewUDP.\n");
\r
270 Wait(r->Event, LISTEN_RETRY_TIME);
\r
275 Debug("UDP Halt.\n");
\r
280 r->Status = LISTENER_STATUS_LISTENING;
\r
281 Debug("Start Listening at UDP Port %u.\n", r->Sock->LocalPort);
\r
291 data = Malloc(UDP_PACKET_SIZE);
\r
302 AddSockSet(&set, r->Sock);
\r
303 Select(&set, SELECT_TIME, NULL, NULL);
\r
305 size = RecvFrom(r->Sock, &src_ip, &src_port, data, UDP_PACKET_SIZE);
\r
306 if (((size == 0) && (r->Sock->IgnoreRecvErr == false)) || r->Halt)
\r
310 Disconnect(r->Sock);
\r
311 ReleaseSock(r->Sock);
\r
313 Debug("UDP Listen Stopped.\n");
\r
318 // UDP パケットを 1 つ受信した
\r
319 if (size != SOCK_LATER)
\r
321 UDPReceivedPacket(r->Cedar, r->Sock, &src_ip, src_port, data, size);
\r
328 void ListenerTCPMainLoop(LISTENER *r)
\r
339 Debug("ListenerTCPMainLoop Starts.\n");
\r
340 r->Status = LISTENER_STATUS_TRYING;
\r
344 bool first_failed = true;
\r
345 Debug("Status = LISTENER_STATUS_TRYING\n");
\r
346 r->Status = LISTENER_STATUS_TRYING;
\r
359 if (r->ShadowIPv6 == false)
\r
361 s = ListenEx(r->Port, r->LocalOnly);
\r
365 s = ListenEx6(r->Port, r->LocalOnly);
\r
373 if (r->ShadowIPv6 == false)
\r
375 SLog(r->Cedar, "LS_LISTENER_START_2", r->Port);
\r
383 first_failed = false;
\r
384 if (r->ShadowIPv6 == false)
\r
386 SLog(r->Cedar, "LS_LISTENER_START_3", r->Port, LISTEN_RETRY_TIME / 1000);
\r
390 interval = LISTEN_RETRY_TIME;
\r
394 if (IsIPv6Supported() == false)
\r
396 interval = LISTEN_RETRY_TIME_NOIPV6;
\r
398 Debug("IPv6 is not supported.\n");
\r
402 Wait(r->Event, interval);
\r
408 Debug("Listener Halt.\n");
\r
413 r->Status = LISTENER_STATUS_LISTENING;
\r
414 Debug("Status = LISTENER_STATUS_LISTENING\n");
\r
429 Debug("Accept()\n");
\r
430 new_sock = Accept(r->Sock);
\r
431 if (new_sock != NULL)
\r
434 Debug("Accepted.\n");
\r
435 TCPAccepted(r, new_sock);
\r
436 ReleaseSock(new_sock);
\r
440 if (r->Halt == false)
\r
442 if ((++num_failed) <= 5)
\r
448 Debug("Accept Canceled.\n");
\r
449 // Accept に失敗した (ソケットが破壊された)
\r
450 // Listen しているソケットを閉じる
\r
461 Debug("Listener Halt.\n");
\r
468 void ListenerThread(THREAD *thread, void *param)
\r
472 if (thread == NULL || param == NULL)
\r
478 r = (LISTENER *)param;
\r
480 r->Thread = thread;
\r
481 AddRef(thread->ref);
\r
482 NoticeThreadInit(thread);
\r
485 switch (r->Protocol)
\r
489 ListenerTCPMainLoop(r);
\r
494 ListenerUDPMainLoop(r);
\r
499 ReleaseListener(r);
\r
503 void StopListener(LISTENER *r)
\r
522 if (r->ShadowIPv6 == false)
\r
524 SLog(r->Cedar, "LS_LISTENER_STOP_1", port);
\r
528 Disconnect(r->Sock);
\r
534 WaitThread(r->Thread, INFINITE);
\r
537 if (r->ShadowIPv6 == false)
\r
539 if (r->ShadowListener != NULL)
\r
541 StopListener(r->ShadowListener);
\r
543 ReleaseListener(r->ShadowListener);
\r
545 r->ShadowListener = NULL;
\r
549 if (r->ShadowIPv6 == false)
\r
551 SLog(r->Cedar, "LS_LISTENER_STOP_2", port);
\r
556 void CleanupListener(LISTENER *r)
\r
564 if (r->Sock != NULL)
\r
566 ReleaseSock(r->Sock);
\r
569 DeleteLock(r->lock);
\r
570 ReleaseThread(r->Thread);
\r
571 ReleaseEvent(r->Event);
\r
573 ReleaseCedar(r->Cedar);
\r
579 void ReleaseListener(LISTENER *r)
\r
587 if (Release(r->ref) == 0)
\r
589 CleanupListener(r);
\r
593 // UDP エントリリストの比較関数
\r
594 int CompareUDPEntry(void *p1, void *p2)
\r
596 UDP_ENTRY *e1, *e2;
\r
597 if (p1 == NULL || p2 == NULL)
\r
601 e1 = *(UDP_ENTRY **)p1;
\r
602 e2 = *(UDP_ENTRY **)p2;
\r
603 if (e1 == NULL || e2 == NULL)
\r
608 if (e1->SessionKey32 > e2->SessionKey32)
\r
612 else if (e1->SessionKey32 == e2->SessionKey32)
\r
623 int CompareListener(void *p1, void *p2)
\r
626 if (p1 == NULL || p2 == NULL)
\r
630 r1 = *(LISTENER **)p1;
\r
631 r2 = *(LISTENER **)p2;
\r
632 if (r1 == NULL || r2 == NULL)
\r
637 if (r1->Protocol > r2->Protocol)
\r
641 else if (r1->Protocol < r2->Protocol)
\r
645 else if (r1->Port > r2->Port)
\r
649 else if (r1->Port < r2->Port)
\r
660 LISTENER *NewListener(CEDAR *cedar, UINT proto, UINT port)
\r
662 return NewListenerEx(cedar, proto, port, TCPAcceptedThread, NULL);
\r
664 LISTENER *NewListenerEx(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param)
\r
666 return NewListenerEx2(cedar, proto, port, proc, thread_param, false);
\r
668 LISTENER *NewListenerEx2(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only)
\r
670 return NewListenerEx3(cedar, proto, port, proc, thread_param, local_only, false);
\r
672 LISTENER *NewListenerEx3(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only, bool shadow_ipv6)
\r
677 if (port == 0 || cedar == NULL)
\r
682 if (proto != LISTENER_TCP && proto != LISTENER_UDP)
\r
687 r = ZeroMalloc(sizeof(LISTENER));
\r
689 r->ThreadProc = proc;
\r
690 r->ThreadParam = thread_param;
\r
692 AddRef(r->Cedar->ref);
\r
693 r->lock = NewLock();
\r
695 r->Protocol = proto;
\r
697 r->Event = NewEvent();
\r
698 r->LocalOnly = local_only;
\r
699 r->ShadowIPv6 = shadow_ipv6;
\r
701 if (r->ShadowIPv6 == false)
\r
703 SLog(cedar, "LS_LISTENER_START_1", port);
\r
707 t = NewThread(ListenerThread, r);
\r
711 if (r->ShadowIPv6 == false)
\r
713 if (r->Cedar->DisableIPv6Listener == false)
\r
716 r->ShadowListener = NewListenerEx3(cedar, proto, port, proc, thread_param,
\r
721 if (r->ShadowIPv6 == false)
\r
724 AddListener(cedar, r);
\r
730 // セッションキーからセッションを取得する
\r
731 SESSION *GetSessionFromUDPEntry(CEDAR *cedar, UINT key32)
\r
741 t.SessionKey32 = key32;
\r
743 LockList(cedar->UDPEntryList);
\r
745 e = Search(cedar->UDPEntryList, &t);
\r
748 UnlockList(cedar->UDPEntryList);
\r
754 UnlockList(cedar->UDPEntryList);
\r
759 // UDP セッションを UDP エントリから削除する
\r
760 void DelUDPEntry(CEDAR *cedar, SESSION *session)
\r
764 if (cedar == NULL || session == NULL)
\r
769 LockList(cedar->UDPEntryList);
\r
771 num = LIST_NUM(cedar->UDPEntryList);
\r
772 for (i = 0;i < num;i++)
\r
774 UDP_ENTRY *e = LIST_DATA(cedar->UDPEntryList, i);
\r
775 if (e->Session == session)
\r
777 ReleaseSession(e->Session);
\r
778 Delete(cedar->UDPEntryList, e);
\r
780 UnlockList(cedar->UDPEntryList);
\r
781 Debug("UDP_Entry Deleted.\n");
\r
786 UnlockList(cedar->UDPEntryList);
\r
789 // UDP セッションを UDP エントリに追加する
\r
790 void AddUDPEntry(CEDAR *cedar, SESSION *session)
\r
794 if (cedar == NULL || session == NULL)
\r
799 e = ZeroMalloc(sizeof(UDP_ENTRY));
\r
800 e->Session = session;
\r
801 e->SessionKey32 = session->SessionKey32;
\r
802 AddRef(session->ref);
\r
804 LockList(cedar->UDPEntryList);
\r
806 Add(cedar->UDPEntryList, e);
\r
808 UnlockList(cedar->UDPEntryList);
\r
810 Debug("UDP_Entry Added.\n");
\r
814 void CleanupUDPEntry(CEDAR *cedar)
\r