source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Listener.c @ a1bae3e

trunk
Last change on this file since a1bae3e was a1bae3e, checked in by mitty <mitty@…>, 12 years ago
  • copy vendor drop to trunk

git-svn-id: https://lab.mitty.jp/svn/lab/trunk@147 7d2118f6-f56c-43e7-95a2-4bb3031d96e7

  • Property mode set to 100644
File size: 18.2 KB
Line 
1// SoftEther UT-VPN SourceCode
2//
3// Copyright (C) 2004-2010 SoftEther Corporation.
4// Copyright (C) 2004-2010 University of Tsukuba, Japan.
5// Copyright (C) 2003-2010 Daiyuu Nobori.
6// All Rights Reserved.
7//
8// http://utvpn.tsukuba.ac.jp/
9//
10// This program is free software; you can redistribute it and/or
11// modify it under the terms of the GNU General Public License
12// version 2 as published by the Free Software Foundation.
13//
14// This program is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License version 2
20// along with this program; if not, write to the Free Software
21// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22//
23// このファイルは GPL バージョン 2 ライセンスで公開されています。
24// 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
25// することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
26// を除去することはできません。改変した著作物を配布する場合は、改変実施者の
27// 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
28//
29// この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
30// ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
31// および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
32// ホストされています。
33// 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
34// および、試験または研究のために利用が行われることを想定して配布
35// しています。
36// SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
37// あります。
38// 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
39// の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
40// いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
41// ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
42// に組み込みさせていただきます。
43//
44// GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
45// 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
46//
47// 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
48// (SoftEther Corporation) およびその他の著作権保持者が保有しています。
49// ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
50// 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
51// ください。
52//
53// お願い: どのような通信ソフトウェアにも通常は必ず未発見の
54// セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
55// UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
56// 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
57// および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
58// 公益保護にご協力いただきますようお願い申し上げます。
59//
60// ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
61// 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
62// を保護するための努力を行います。
63//
64// ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
65// 日本国内の脆弱性情報届出受付公的機関:
66//         独立行政法人 情報処理推進機構
67//         http://www.ipa.go.jp/security/vuln/report/
68//
69// 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
70// 連絡先: http://www.softether.co.jp/jp/contact/
71
72// -----------------------------------------------
73// [ChangeLog]
74// 2010.05.20
75//  新規リリース by SoftEther
76// -----------------------------------------------
77
78// Listener.c
79// リスナー モジュール
80
81#include "CedarPch.h"
82
83// UDP パケットを 1 つ受信した
84void UDPReceivedPacket(CEDAR *cedar, SOCK *s, IP *ip, UINT port, void *data, UINT size)
85{
86    SESSION *session;
87    UINT *key32;
88    UCHAR *buf;
89    CONNECTION *c;
90    // 引数チェック
91    if (s == NULL || ip == NULL || data == NULL || size == 0 || cedar == NULL)
92    {
93        return;
94    }
95
96    if (size < 16)
97    {
98        // パケットサイズが足らないので無視
99        return;
100    }
101    buf = (UCHAR *)data;
102    key32 = (UINT *)(buf + 4);
103
104
105    // Key32 の値からセッションを取得
106    session = GetSessionFromUDPEntry(cedar, Endian32(*key32));
107    if (session == NULL)
108    {
109        Debug("Invalid UDP Session Key 32: 0x%X\n", *key32);
110        return;
111    }
112
113    c = session->Connection;
114
115    // データを書き込む
116    PutUDPPacketData(c, buf, size);
117
118    // コネクションに関連付けられている UDP ソケットを書き換える
119    Lock(c->lock);
120    {
121        if (c->Protocol == CONNECTION_UDP)
122        {
123            if (c->Udp->s != s)
124            {
125                if (c->Udp->s != NULL)
126                {
127                    ReleaseSock(c->Udp->s);
128                }
129                AddRef(s->ref);
130                c->Udp->s = s;
131            }
132            Copy(&c->Udp->ip, ip, sizeof(UINT));
133            c->Udp->port = port;
134        }
135    }
136    Unlock(c->lock);
137
138    // キャンセル発動
139    Cancel(session->Cancel1);
140
141    // セッションを解放
142    ReleaseSession(session);
143}
144
145// Accept された TCP コネクションを処理するスレッド
146void TCPAcceptedThread(THREAD *t, void *param)
147{
148    TCP_ACCEPTED_PARAM *data;
149    LISTENER *r;
150    SOCK *s;
151    CONNECTION *c;
152    bool flag1;
153    char tmp[128];
154    // 引数チェック
155    if (t == NULL || param == NULL)
156    {
157        return;
158    }
159
160    // 初期化
161    data = (TCP_ACCEPTED_PARAM *)param;
162    r = data->r;
163    s = data->s;
164    AddRef(r->ref);
165    AddRef(s->ref);
166
167    // コネクションの作成
168    c = NewServerConnection(r->Cedar, s, t);
169
170    // Cedar に一時コネクションとして登録する
171    AddConnection(c->Cedar, c);
172
173    NoticeThreadInit(t);
174
175    AcceptInit(s);
176    StrCpy(c->ClientHostname, sizeof(c->ClientHostname), s->RemoteHostname);
177    IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
178    SLog(r->Cedar, "LS_LISTENER_ACCEPT", r->Port, tmp, s->RemoteHostname, s->RemotePort);
179
180    // 受付
181    ConnectionAccept(c);
182    flag1 = c->flag1;
183
184    // 解放
185    SLog(r->Cedar, "LS_CONNECTION_END_1", c->Name);
186    ReleaseConnection(c);
187
188    // 解放
189    if (flag1 == false)
190    {
191        Debug("%s %u flag1 == false\n", __FILE__, __LINE__);
192        IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
193        SLog(r->Cedar, "LS_LISTENER_DISCONNECT", tmp, s->RemotePort);
194        Disconnect(s);
195    }
196    ReleaseSock(s);
197    ReleaseListener(r);
198}
199
200// TCP で Accept されたコネクションがある場合はここに飛ぶ
201void TCPAccepted(LISTENER *r, SOCK *s)
202{
203    TCP_ACCEPTED_PARAM *data;
204    THREAD *t;
205    char tmp[MAX_SIZE];
206    UINT num_clients_from_this_ip = 0;
207    CEDAR *cedar;
208    // 引数チェック
209    if (r == NULL || s == NULL)
210    {
211        return;
212    }
213
214    cedar = r->Cedar;
215
216    num_clients_from_this_ip = GetNumIpClient(&s->RemoteIP);
217
218    IPToStr(tmp, sizeof(tmp), &s->RemoteIP);
219
220    data = ZeroMalloc(sizeof(TCP_ACCEPTED_PARAM));
221    data->r = r;
222    data->s = s;
223
224    if (r->ThreadProc == TCPAcceptedThread)
225    {
226        Inc(cedar->AcceptingSockets);
227    }
228
229    t = NewThread(r->ThreadProc, data);
230    WaitThreadInit(t);
231    Free(data);
232    ReleaseThread(t);
233}
234
235// UDP リスナーメインループ
236void ListenerUDPMainLoop(LISTENER *r)
237{
238    UCHAR *data;
239    // 引数チェック
240    if (r == NULL)
241    {
242        return;
243    }
244
245    Debug("ListenerUDPMainLoop Starts.\n");
246    r->Status = LISTENER_STATUS_TRYING;
247
248    while (true)
249    {
250        // UDP ポートでの待機を試みる
251        while (true)
252        {
253            // 停止フラグ検査
254            if (r->Halt)
255            {
256                // 停止
257                return;
258            }
259
260            Debug("NewUDP()\n");
261            r->Sock = NewUDP(r->Port);
262            if (r->Sock != NULL)
263            {
264                // 待機成功
265                break;
266            }
267
268            // 待機失敗
269            Debug("Failed to NewUDP.\n");
270            Wait(r->Event, LISTEN_RETRY_TIME);
271
272            // 停止フラグ検査
273            if (r->Halt)
274            {
275                Debug("UDP Halt.\n");
276                return;
277            }
278        }
279
280        r->Status = LISTENER_STATUS_LISTENING;
281        Debug("Start Listening at UDP Port %u.\n", r->Sock->LocalPort);
282
283        // 停止フラグ検査
284        if (r->Halt)
285        {
286            // 停止
287            goto STOP;
288        }
289
290        // バッファ領域の確保
291        data = Malloc(UDP_PACKET_SIZE);
292
293        // 次のパケットを読み込む
294        while (true)
295        {
296            IP src_ip;
297            UINT src_port;
298            UINT size;
299            SOCKSET set;
300
301            InitSockSet(&set);
302            AddSockSet(&set, r->Sock);
303            Select(&set, SELECT_TIME, NULL, NULL);
304
305            size = RecvFrom(r->Sock, &src_ip, &src_port, data, UDP_PACKET_SIZE);
306            if (((size == 0) && (r->Sock->IgnoreRecvErr == false)) || r->Halt)
307            {
308                // エラーが発生した
309STOP:
310                Disconnect(r->Sock);
311                ReleaseSock(r->Sock);
312                r->Sock = NULL;
313                Debug("UDP Listen Stopped.\n");
314                Free(data);
315                break;
316            }
317
318            // UDP パケットを 1 つ受信した
319            if (size != SOCK_LATER)
320            {
321                UDPReceivedPacket(r->Cedar, r->Sock, &src_ip, src_port, data, size);
322            }
323        }
324    }
325}
326
327// TCP リスナーメインループ
328void ListenerTCPMainLoop(LISTENER *r)
329{
330    SOCK *new_sock;
331    SOCK *s;
332    UINT num_failed;
333    // 引数チェック
334    if (r == NULL)
335    {
336        return;
337    }
338
339    Debug("ListenerTCPMainLoop Starts.\n");
340    r->Status = LISTENER_STATUS_TRYING;
341
342    while (true)
343    {
344        bool first_failed = true;
345        Debug("Status = LISTENER_STATUS_TRYING\n");
346        r->Status = LISTENER_STATUS_TRYING;
347
348        // Listen を試みる
349        while (true)
350        {
351            UINT interval;
352            // 停止フラグ検査
353            if (r->Halt)
354            {
355                // 停止
356                return;
357            }
358
359            if (r->ShadowIPv6 == false)
360            {
361                s = ListenEx(r->Port, r->LocalOnly);
362            }
363            else
364            {
365                s = ListenEx6(r->Port, r->LocalOnly);
366            }
367
368            if (s != NULL)
369            {
370                // Listen 成功
371                AddRef(s->ref);
372                r->Sock = s;
373                if (r->ShadowIPv6 == false)
374                {
375                    SLog(r->Cedar, "LS_LISTENER_START_2", r->Port);
376                }
377                break;
378            }
379
380            // Listen 失敗
381            if (first_failed)
382            {
383                first_failed = false;
384                if (r->ShadowIPv6 == false)
385                {
386                    SLog(r->Cedar, "LS_LISTENER_START_3", r->Port, LISTEN_RETRY_TIME / 1000);
387                }
388            }
389
390            interval = LISTEN_RETRY_TIME;
391
392            if (r->ShadowIPv6)
393            {
394                if (IsIPv6Supported() == false)
395                {
396                    interval = LISTEN_RETRY_TIME_NOIPV6;
397
398                    Debug("IPv6 is not supported.\n");
399                }
400            }
401
402            Wait(r->Event, interval);
403
404            // 停止フラグ検査
405            if (r->Halt)
406            {
407                // 停止
408                Debug("Listener Halt.\n");
409                return;
410            }
411        }
412
413        r->Status = LISTENER_STATUS_LISTENING;
414        Debug("Status = LISTENER_STATUS_LISTENING\n");
415
416        // 停止フラグ検査
417        if (r->Halt)
418        {
419            // 停止
420            goto STOP;
421        }
422
423        num_failed = 0;
424
425        // Accpet ループ
426        while (true)
427        {
428            // Accept を行う
429            Debug("Accept()\n");
430            new_sock = Accept(r->Sock);
431            if (new_sock != NULL)
432            {
433                // Accept 成功
434                Debug("Accepted.\n");
435                TCPAccepted(r, new_sock);
436                ReleaseSock(new_sock);
437            }
438            else
439            {
440                if (r->Halt == false)
441                {
442                    if ((++num_failed) <= 5)
443                    {
444                        continue;
445                    }
446                }
447STOP:
448                Debug("Accept Canceled.\n");
449                // Accept に失敗した (ソケットが破壊された)
450                // Listen しているソケットを閉じる
451                Disconnect(s);
452                ReleaseSock(s);
453                break;
454            }
455        }
456
457        // 停止フラグ検査
458        if (r->Halt)
459        {
460            // 停止
461            Debug("Listener Halt.\n");
462            return;
463        }
464    }
465}
466
467// リスナーのスレッド
468void ListenerThread(THREAD *thread, void *param)
469{
470    LISTENER *r;
471    // 引数チェック
472    if (thread == NULL || param == NULL)
473    {
474        return;
475    }
476
477    // 初期化
478    r = (LISTENER *)param;
479    AddRef(r->ref);
480    r->Thread = thread;
481    AddRef(thread->ref);
482    NoticeThreadInit(thread);
483
484    // メインループ
485    switch (r->Protocol)
486    {
487    case LISTENER_TCP:
488        // TCP プロトコル
489        ListenerTCPMainLoop(r);
490        break;
491
492    case LISTENER_UDP:
493        // UDP プロトコル
494        ListenerUDPMainLoop(r);
495        break;
496    }
497
498    // 解放
499    ReleaseListener(r);
500}
501
502// リスナーの停止
503void StopListener(LISTENER *r)
504{
505    UINT port;
506    // 引数チェック
507    if (r == NULL)
508    {
509        return;
510    }
511
512    if (r->Halt)
513    {
514        return;
515    }
516
517    port = r->Port;
518
519    // 停止フラグセット
520    r->Halt = true;
521
522    if (r->ShadowIPv6 == false)
523    {
524        SLog(r->Cedar, "LS_LISTENER_STOP_1", port);
525    }
526
527    // ソケットを閉じる
528    Disconnect(r->Sock);
529
530    // イベントのセット
531    Set(r->Event);
532
533    // スレッドが停止するまで待機
534    WaitThread(r->Thread, INFINITE);
535
536    // 影のリスナーを停止させる
537    if (r->ShadowIPv6 == false)
538    {
539        if (r->ShadowListener != NULL)
540        {
541            StopListener(r->ShadowListener);
542
543            ReleaseListener(r->ShadowListener);
544
545            r->ShadowListener = NULL;
546        }
547    }
548
549    if (r->ShadowIPv6 == false)
550    {
551        SLog(r->Cedar, "LS_LISTENER_STOP_2", port);
552    }
553}
554
555// リスナーのクリーンアップ
556void CleanupListener(LISTENER *r)
557{
558    // 引数チェック
559    if (r == NULL)
560    {
561        return;
562    }
563
564    if (r->Sock != NULL)
565    {
566        ReleaseSock(r->Sock);
567    }
568
569    DeleteLock(r->lock);
570    ReleaseThread(r->Thread);
571    ReleaseEvent(r->Event);
572
573    ReleaseCedar(r->Cedar);
574
575    Free(r);
576}
577
578// リスナーの解放
579void ReleaseListener(LISTENER *r)
580{
581    // 引数チェック
582    if (r == NULL)
583    {
584        return;
585    }
586
587    if (Release(r->ref) == 0)
588    {
589        CleanupListener(r);
590    }
591}
592
593// UDP エントリリストの比較関数
594int CompareUDPEntry(void *p1, void *p2)
595{
596    UDP_ENTRY *e1, *e2;
597    if (p1 == NULL || p2 == NULL)
598    {
599        return 0;
600    }
601    e1 = *(UDP_ENTRY **)p1;
602    e2 = *(UDP_ENTRY **)p2;
603    if (e1 == NULL || e2 == NULL)
604    {
605        return 0;
606    }
607
608    if (e1->SessionKey32 > e2->SessionKey32)
609    {
610        return 1;
611    }
612    else if (e1->SessionKey32 == e2->SessionKey32)
613    {
614        return 0;
615    }
616    else
617    {
618        return -1;
619    }
620}
621
622// リスナーの比較関数
623int CompareListener(void *p1, void *p2)
624{
625    LISTENER *r1, *r2;
626    if (p1 == NULL || p2 == NULL)
627    {
628        return 0;
629    }
630    r1 = *(LISTENER **)p1;
631    r2 = *(LISTENER **)p2;
632    if (r1 == NULL || r2 == NULL)
633    {
634        return 0;
635    }
636
637    if (r1->Protocol > r2->Protocol)
638    {
639        return 1;
640    }
641    else if (r1->Protocol < r2->Protocol)
642    {
643        return -1;
644    }
645    else if (r1->Port > r2->Port)
646    {
647        return 1;
648    }
649    else if (r1->Port < r2->Port)
650    {
651        return -1;
652    }
653    else
654    {
655        return 0;
656    }
657}
658
659// 新しいリスナーの作成
660LISTENER *NewListener(CEDAR *cedar, UINT proto, UINT port)
661{
662    return NewListenerEx(cedar, proto, port, TCPAcceptedThread, NULL);
663}
664LISTENER *NewListenerEx(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param)
665{
666    return NewListenerEx2(cedar, proto, port, proc, thread_param, false);
667}
668LISTENER *NewListenerEx2(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only)
669{
670    return NewListenerEx3(cedar, proto, port, proc, thread_param, local_only, false);
671}
672LISTENER *NewListenerEx3(CEDAR *cedar, UINT proto, UINT port, THREAD_PROC *proc, void *thread_param, bool local_only, bool shadow_ipv6)
673{
674    LISTENER *r;
675    THREAD *t;
676    // 引数チェック
677    if (port == 0 || cedar == NULL)
678    {
679        return NULL;
680    }
681    // プロトコル番号のチェック
682    if (proto != LISTENER_TCP && proto != LISTENER_UDP)
683    {
684        return NULL;
685    }
686
687    r = ZeroMalloc(sizeof(LISTENER));
688
689    r->ThreadProc = proc;
690    r->ThreadParam = thread_param;
691    r->Cedar = cedar;
692    AddRef(r->Cedar->ref);
693    r->lock = NewLock();
694    r->ref = NewRef();
695    r->Protocol = proto;
696    r->Port = port;
697    r->Event = NewEvent();
698    r->LocalOnly = local_only;
699    r->ShadowIPv6 = shadow_ipv6;
700
701    if (r->ShadowIPv6 == false)
702    {
703        SLog(cedar, "LS_LISTENER_START_1", port);
704    }
705
706    // スレッドの作成
707    t = NewThread(ListenerThread, r);
708    WaitThreadInit(t);
709    ReleaseThread(t);
710
711    if (r->ShadowIPv6 == false)
712    {
713        if (r->Cedar->DisableIPv6Listener == false)
714        {
715            // 影のリスナーを追加する
716            r->ShadowListener = NewListenerEx3(cedar, proto, port, proc, thread_param,
717                local_only, true);
718        }
719    }
720
721    if (r->ShadowIPv6 == false)
722    {
723        // Cedar に追加
724        AddListener(cedar, r);
725    }
726
727    return r;
728}
729
730// セッションキーからセッションを取得する
731SESSION *GetSessionFromUDPEntry(CEDAR *cedar, UINT key32)
732{
733    UDP_ENTRY *e, t;
734    SESSION *s;
735    // 引数チェック
736    if (cedar == NULL)
737    {
738        return NULL;
739    }
740
741    t.SessionKey32 = key32;
742
743    LockList(cedar->UDPEntryList);
744    {
745        e = Search(cedar->UDPEntryList, &t);
746        if (e == NULL)
747        {
748            UnlockList(cedar->UDPEntryList);
749            return NULL;
750        }
751        s = e->Session;
752        AddRef(s->ref);
753    }
754    UnlockList(cedar->UDPEntryList);
755
756    return s;
757}
758
759// UDP セッションを UDP エントリから削除する
760void DelUDPEntry(CEDAR *cedar, SESSION *session)
761{
762    UINT num, i;
763    // 引数チェック
764    if (cedar == NULL || session == NULL)
765    {
766        return;
767    }
768
769    LockList(cedar->UDPEntryList);
770    {
771        num = LIST_NUM(cedar->UDPEntryList);
772        for (i = 0;i < num;i++)
773        {
774            UDP_ENTRY *e = LIST_DATA(cedar->UDPEntryList, i);
775            if (e->Session == session)
776            {
777                ReleaseSession(e->Session);
778                Delete(cedar->UDPEntryList, e);
779                Free(e);
780                UnlockList(cedar->UDPEntryList);
781                Debug("UDP_Entry Deleted.\n");
782                return;
783            }
784        }
785    }
786    UnlockList(cedar->UDPEntryList);
787}
788
789// UDP セッションを UDP エントリに追加する
790void AddUDPEntry(CEDAR *cedar, SESSION *session)
791{
792    UDP_ENTRY *e;
793    // 引数チェック
794    if (cedar == NULL || session == NULL)
795    {
796        return;
797    }
798
799    e = ZeroMalloc(sizeof(UDP_ENTRY));
800    e->Session = session;
801    e->SessionKey32 = session->SessionKey32;
802    AddRef(session->ref);
803
804    LockList(cedar->UDPEntryList);
805    {
806        Add(cedar->UDPEntryList, e);
807    }
808    UnlockList(cedar->UDPEntryList);
809
810    Debug("UDP_Entry Added.\n");
811}
812
813// UDP エントリのクリア
814void CleanupUDPEntry(CEDAR *cedar)
815{
816    // 引数チェック
817    if (cedar == NULL)
818    {
819        return;
820    }
821}
822
823
Note: See TracBrowser for help on using the repository browser.