source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Server.c @ 072e48b

trunk
Last change on this file since 072e48b 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: 202.6 KB
RevLine 
[a1bae3e]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// Server.c
79// サーバーマネージャ
80
81#include "CedarPch.h"
82
83static SERVER *server = NULL;
84static LOCK *server_lock = NULL;
85char *SERVER_CONFIG_FILE_NAME = "@vpn_server.config";
86char *BRIDGE_CONFIG_FILE_NAME = "@vpn_bridge.config";
87
88static bool server_reset_setting = false;
89
90// VPN Server に登録されているユーザーオブジェクト数が多すぎるかどうか取得
91bool SiTooManyUserObjectsInServer(SERVER *s, bool oneMore)
92{
93    LICENSE_STATUS st;
94    UINT num;
95    // 引数チェック
96    if (s == NULL)
97    {
98        return false;
99    }
100
101    num = SiGetServerNumUserObjects(s);
102
103    Zero(&st, sizeof(st));
104
105    LiParseCurrentLicenseStatus(s->LicenseSystem, &st);
106
107    if (st.NumUserLicense == INFINITE)
108    {
109        return false;
110    }
111
112    if (oneMore)
113    {
114        st.NumUserLicense++;
115    }
116
117    if (st.NumUserLicense <= num)
118    {
119        return true;
120    }
121
122    return false;
123}
124
125// VPN Server に登録されているユーザーオブジェクト数を取得
126UINT SiGetServerNumUserObjects(SERVER *s)
127{
128    CEDAR *c;
129    UINT ret = 0;
130    // 引数チェック
131    if (s == NULL)
132    {
133        return 0;
134    }
135
136    c = s->Cedar;
137
138    LockList(c->HubList);
139    {
140        UINT i;
141        for (i = 0;i < LIST_NUM(c->HubList);i++)
142        {
143            HUB *h = LIST_DATA(c->HubList, i);
144
145            if (h->HubDb != NULL)
146            {
147                ret += LIST_NUM(h->HubDb->UserList);
148            }
149        }
150    }
151    UnlockList(c->HubList);
152
153    return ret;
154}
155
156
157typedef struct SI_DEBUG_PROC_LIST
158{
159    UINT Id;
160    char *Description;
161    char *Args;
162    SI_DEBUG_PROC *Proc;
163} SI_DEBUG_PROC_LIST;
164
165// デバッグ機能
166UINT SiDebug(SERVER *s, RPC_TEST *ret, UINT i, char *str)
167{
168    SI_DEBUG_PROC_LIST proc_list[] =
169    {
170        {1, "Hello World", "<test string>", SiDebugProcHelloWorld},
171        {2, "Terminate process now", "", SiDebugProcExit},
172        {3, "Write memory dumpfile", "", SiDebugProcDump},
173        {4, "Restore process priority", "", SiDebugProcRestorePriority},
174        {5, "Set the process priority high", "", SiDebugProcSetHighPriority},
175        {6, "Get the .exe filename of the process", "", SiDebugProcGetExeFileName},
176        {7, "Crash the process", "", SiDebugProcCrash},
177    };
178    UINT num_proc_list = sizeof(proc_list) / sizeof(proc_list[0]);
179    UINT j;
180    UINT ret_value = ERR_NO_ERROR;
181    // 引数チェック
182    if (s == NULL || ret == NULL)
183    {
184        return ERR_INVALID_PARAMETER;
185    }
186
187    if (i == 0)
188    {
189        char tmp[MAX_SIZE];
190        Zero(ret, sizeof(RPC_TEST));
191
192        StrCat(ret->StrValue, sizeof(ret->StrValue),
193            "\n--- Debug Functions List --\n");
194
195        for (j = 0;j < num_proc_list;j++)
196        {
197            SI_DEBUG_PROC_LIST *p = &proc_list[j];
198
199            if (IsEmptyStr(p->Args) == false)
200            {
201                Format(tmp, sizeof(tmp),
202                    " %u: %s - Usage: %u /ARGS:\"%s\"\n",
203                    p->Id, p->Description, p->Id, p->Args);
204            }
205            else
206            {
207                Format(tmp, sizeof(tmp),
208                    " %u: %s - Usage: %u\n",
209                    p->Id, p->Description, p->Id);
210            }
211
212            StrCat(ret->StrValue, sizeof(ret->StrValue), tmp);
213        }
214    }
215    else
216    {
217        ret_value = ERR_NOT_SUPPORTED;
218
219        for (j = 0;j < num_proc_list;j++)
220        {
221            SI_DEBUG_PROC_LIST *p = &proc_list[j];
222
223            if (p->Id == i)
224            {
225                ret_value = p->Proc(s, str, ret->StrValue, sizeof(ret->StrValue));
226
227                if (ret_value == ERR_NO_ERROR && IsEmptyStr(ret->StrValue))
228                {
229                    StrCpy(ret->StrValue, sizeof(ret->StrValue), "Ok.");
230                }
231                break;
232            }
233        }
234    }
235
236    return ret_value;
237}
238UINT SiDebugProcHelloWorld(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
239{
240    // 引数チェック
241    if (s == NULL || in_str == NULL || ret_str == NULL)
242    {
243        return ERR_INVALID_PARAMETER;
244    }
245
246    Format(ret_str, ret_str_size, "Hello World %s\n", in_str);
247
248    return ERR_NO_ERROR;
249}
250UINT SiDebugProcExit(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
251{
252    // 引数チェック
253    if (s == NULL || in_str == NULL || ret_str == NULL)
254    {
255        return ERR_INVALID_PARAMETER;
256    }
257
258    _exit(1);
259
260    return ERR_NO_ERROR;
261}
262UINT SiDebugProcDump(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
263{
264    // 引数チェック
265    if (s == NULL || in_str == NULL || ret_str == NULL)
266    {
267        return ERR_INVALID_PARAMETER;
268    }
269
270#ifdef  OS_WIN32
271    MsWriteMinidump(NULL, NULL);
272#else   // OS_WIN32
273    return ERR_NOT_SUPPORTED;
274#endif  // OS_WIN32
275
276    return ERR_NO_ERROR;
277}
278UINT SiDebugProcRestorePriority(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
279{
280    // 引数チェック
281    if (s == NULL || in_str == NULL || ret_str == NULL)
282    {
283        return ERR_INVALID_PARAMETER;
284    }
285
286    OSRestorePriority();
287
288    return ERR_NO_ERROR;
289}
290UINT SiDebugProcSetHighPriority(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
291{
292    // 引数チェック
293    if (s == NULL || in_str == NULL || ret_str == NULL)
294    {
295        return ERR_INVALID_PARAMETER;
296    }
297
298    OSSetHighPriority();
299
300    return ERR_NO_ERROR;
301}
302UINT SiDebugProcGetExeFileName(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
303{
304    // 引数チェック
305    if (s == NULL || in_str == NULL || ret_str == NULL)
306    {
307        return ERR_INVALID_PARAMETER;
308    }
309
310    GetExeName(ret_str, ret_str_size);
311
312    return ERR_NO_ERROR;
313}
314UINT SiDebugProcCrash(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
315{
316    // 引数チェック
317    if (s == NULL || in_str == NULL || ret_str == NULL)
318    {
319        return ERR_INVALID_PARAMETER;
320    }
321
322    CrashNow();
323
324    return ERR_NO_ERROR;
325}
326
327// デバッグログの書き込み
328void SiDebugLog(SERVER *s, char *msg)
329{
330    // 引数チェック
331    if (s == NULL || msg == NULL)
332    {
333        return;
334    }
335
336    if (s->DebugLog != NULL)
337    {
338        WriteTinyLog(s->DebugLog, msg);
339    }
340}
341
342// デッドロック検査メイン
343void SiCheckDeadLockMain(SERVER *s, UINT timeout)
344{
345    CEDAR *cedar;
346    // 引数チェック
347    if (s == NULL)
348    {
349        return;
350    }
351
352    Debug("SiCheckDeadLockMain Start.\n");
353
354    cedar = s->Cedar;
355
356    if (s->ServerListenerList != NULL)
357    {
358        CheckDeadLock(s->ServerListenerList->lock, timeout, "s->ServerListenerList->lock");
359    }
360
361    CheckDeadLock(s->lock, timeout, "s->lock");
362
363    if (s->FarmMemberList != NULL)
364    {
365        CheckDeadLock(s->FarmMemberList->lock, timeout, "s->FarmMemberList->lock");
366    }
367
368    if (s->HubCreateHistoryList != NULL)
369    {
370        CheckDeadLock(s->HubCreateHistoryList->lock, timeout, "s->HubCreateHistoryList->lock");
371    }
372
373    CheckDeadLock(s->CapsCacheLock, timeout, "s->CapsCacheLock");
374
375    CheckDeadLock(s->TasksFromFarmControllerLock, timeout, "s->TasksFromFarmControllerLock");
376
377    if (cedar != NULL)
378    {
379        if (cedar->HubList != NULL)
380        {
381            CheckDeadLock(cedar->HubList->lock, timeout, "cedar->HubList->lock");
382        }
383
384        if (cedar->ListenerList != NULL)
385        {
386            UINT i;
387            LIST *o = NewListFast(NULL);
388
389            CheckDeadLock(cedar->ListenerList->lock, timeout, "cedar->ListenerList->lock");
390
391            LockList(cedar->ListenerList);
392            {
393                for (i = 0;i < LIST_NUM(cedar->ListenerList);i++)
394                {
395                    LISTENER *r = LIST_DATA(cedar->ListenerList, i);
396
397                    AddRef(r->ref);
398
399                    Add(o, r);
400                }
401            }
402            UnlockList(cedar->ListenerList);
403
404            for (i = 0;i < LIST_NUM(o);i++)
405            {
406                LISTENER *r = LIST_DATA(o, i);
407
408                ReleaseListener(r);
409            }
410
411            ReleaseList(o);
412        }
413
414        if (cedar->ConnectionList != NULL)
415        {
416            CheckDeadLock(cedar->ConnectionList->lock, timeout, "cedar->ConnectionList->lock");
417        }
418
419        if (cedar->CaList != NULL)
420        {
421            CheckDeadLock(cedar->CaList->lock, timeout, "cedar->CaList->lock");
422        }
423
424        if (cedar->TrafficLock != NULL)
425        {
426            CheckDeadLock(cedar->TrafficLock, timeout, "cedar->TrafficLock");
427        }
428
429        if (cedar->TrafficDiffList != NULL)
430        {
431            CheckDeadLock(cedar->TrafficDiffList->lock, timeout, "cedar->TrafficDiffList->lock");
432        }
433
434        if (cedar->LocalBridgeList != NULL)
435        {
436            CheckDeadLock(cedar->LocalBridgeList->lock, timeout, "cedar->LocalBridgeList->lock");
437        }
438
439        if (cedar->L3SwList != NULL)
440        {
441            CheckDeadLock(cedar->L3SwList->lock, timeout, "cedar->L3SwList->lock");
442        }
443    }
444
445    Debug("SiCheckDeadLockMain Finish.\n");
446}
447
448// デッドロックチェックスレッド
449void SiDeadLockCheckThread(THREAD *t, void *param)
450{
451    SERVER *s = (SERVER *)param;
452    // 引数チェック
453    if (s == NULL || t == NULL)
454    {
455        return;
456    }
457
458    while (true)
459    {
460        Wait(s->DeadLockWaitEvent, SERVER_DEADLOCK_CHECK_SPAN);
461
462        if (s->HaltDeadLockThread)
463        {
464            break;
465        }
466
467        SiCheckDeadLockMain(s, SERVER_DEADLOCK_CHECK_TIMEOUT);
468    }
469}
470
471// デッドロックチェックの初期化
472void SiInitDeadLockCheck(SERVER *s)
473{
474    // 引数チェック
475    if (s == NULL)
476    {
477        return;
478    }
479    if (s->DisableDeadLockCheck)
480    {
481        return;
482    }
483
484    s->HaltDeadLockThread = false;
485    s->DeadLockWaitEvent = NewEvent();
486    s->DeadLockCheckThread = NewThread(SiDeadLockCheckThread, s);
487}
488
489// デッドロックチェックの解放
490void SiFreeDeadLockCheck(SERVER *s)
491{
492    // 引数チェック
493    if (s == NULL)
494    {
495        return;
496    }
497
498    if (s->DeadLockCheckThread == NULL)
499    {
500        return;
501    }
502
503    s->HaltDeadLockThread = true;
504    Set(s->DeadLockWaitEvent);
505
506    WaitThread(s->DeadLockCheckThread, INFINITE);
507
508    ReleaseThread(s->DeadLockCheckThread);
509    s->DeadLockCheckThread = NULL;
510
511    ReleaseEvent(s->DeadLockWaitEvent);
512    s->DeadLockWaitEvent = NULL;
513
514    s->HaltDeadLockThread = false;
515}
516
517// 指定した仮想 HUB が作成履歴に登録されているかどうか調べる
518bool SiIsHubRegistedOnCreateHistory(SERVER *s, char *name)
519{
520    UINT i;
521    bool ret = false;
522    // 引数チェック
523    if (s == NULL || name == NULL)
524    {
525        return false;
526    }
527
528    SiDeleteOldHubCreateHistory(s);
529
530    LockList(s->HubCreateHistoryList);
531    {
532        for (i = 0;i < LIST_NUM(s->HubCreateHistoryList);i++)
533        {
534            SERVER_HUB_CREATE_HISTORY *h = LIST_DATA(s->HubCreateHistoryList, i);
535
536            if (StrCmpi(h->HubName, name) == 0)
537            {
538                ret = true;
539                break;
540            }
541        }
542    }
543    UnlockList(s->HubCreateHistoryList);
544
545    return ret;
546}
547
548// 仮想 HUB 作成履歴の削除
549void SiDelHubCreateHistory(SERVER *s, char *name)
550{
551    UINT i;
552    // 引数チェック
553    if (s == NULL || name == NULL)
554    {
555        return;
556    }
557
558    LockList(s->HubCreateHistoryList);
559    {
560        SERVER_HUB_CREATE_HISTORY *hh = NULL;
561        for (i = 0;i < LIST_NUM(s->HubCreateHistoryList);i++)
562        {
563            SERVER_HUB_CREATE_HISTORY *h = LIST_DATA(s->HubCreateHistoryList, i);
564
565            if (StrCmpi(h->HubName, name) == 0)
566            {
567                Delete(s->HubCreateHistoryList, h);
568                Free(h);
569                break;
570            }
571        }
572    }
573    UnlockList(s->HubCreateHistoryList);
574
575    SiDeleteOldHubCreateHistory(s);
576}
577
578// 仮想 HUB 作成履歴への登録
579void SiAddHubCreateHistory(SERVER *s, char *name)
580{
581    UINT i;
582    // 引数チェック
583    if (s == NULL || name == NULL)
584    {
585        return;
586    }
587
588    LockList(s->HubCreateHistoryList);
589    {
590        SERVER_HUB_CREATE_HISTORY *hh = NULL;
591        for (i = 0;i < LIST_NUM(s->HubCreateHistoryList);i++)
592        {
593            SERVER_HUB_CREATE_HISTORY *h = LIST_DATA(s->HubCreateHistoryList, i);
594
595            if (StrCmpi(h->HubName, name) == 0)
596            {
597                hh = h;
598                break;
599            }
600        }
601
602        if (hh == NULL)
603        {
604            hh = ZeroMalloc(sizeof(SERVER_HUB_CREATE_HISTORY));
605            StrCpy(hh->HubName, sizeof(hh->HubName), name);
606
607            Add(s->HubCreateHistoryList, hh);
608        }
609
610        hh->CreatedTime = Tick64();
611    }
612    UnlockList(s->HubCreateHistoryList);
613
614    SiDeleteOldHubCreateHistory(s);
615}
616
617// 古くなった仮想 HUB 作成履歴の削除
618void SiDeleteOldHubCreateHistory(SERVER *s)
619{
620    UINT i;
621    LIST *o;
622    // 引数チェック
623    if (s == NULL)
624    {
625        return;
626    }
627
628    LockList(s->HubCreateHistoryList);
629    {
630        o = NewListFast(NULL);
631
632        for (i = 0;i < LIST_NUM(s->HubCreateHistoryList);i++)
633        {
634            SERVER_HUB_CREATE_HISTORY *h = LIST_DATA(s->HubCreateHistoryList, i);
635
636            if ((h->CreatedTime + ((UINT64)TICKET_EXPIRES)) <= Tick64())
637            {
638                // 有効期限切れ
639                Add(o, h);
640            }
641        }
642
643        for (i = 0;i < LIST_NUM(o);i++)
644        {
645            SERVER_HUB_CREATE_HISTORY *h = LIST_DATA(o, i);
646
647            Delete(s->HubCreateHistoryList, h);
648
649            Free(h);
650        }
651
652        ReleaseList(o);
653    }
654    UnlockList(s->HubCreateHistoryList);
655}
656
657// 仮想 HUB 作成履歴の初期化
658void SiInitHubCreateHistory(SERVER *s)
659{
660    // 引数チェック
661    if (s == NULL)
662    {
663        return;
664    }
665
666    s->HubCreateHistoryList = NewList(NULL);
667}
668
669// 仮想 HUB 作成履歴の解放
670void SiFreeHubCreateHistory(SERVER *s)
671{
672    UINT i;
673    // 引数チェック
674    if (s == NULL)
675    {
676        return;
677    }
678
679    for (i = 0;i < LIST_NUM(s->HubCreateHistoryList);i++)
680    {
681        SERVER_HUB_CREATE_HISTORY *h = LIST_DATA(s->HubCreateHistoryList, i);
682
683        Free(h);
684    }
685
686    ReleaseList(s->HubCreateHistoryList);
687
688    s->HubCreateHistoryList = NULL;
689}
690
691// Admin Pack のインストーラ作成キットで作成した VPN Client が
692// 接続可能なサーバーかどうか判別
693bool IsAdminPackSupportedServerProduct(char *name)
694{
695    // 引数チェック
696    if (name == NULL)
697    {
698        return true;
699    }
700
701    return true;
702
703#if 0
704    // SoftEther UT-VPN ではこの制限はなくなった
705    if (SearchStrEx(name, "home", 0, false) != INFINITE)
706    {
707        return false;
708    }
709
710    if (SearchStrEx(name, "soho", 0, false) != INFINITE)
711    {
712        return false;
713    }
714
715    if (SearchStrEx(name, "small business", 0, false) != INFINITE)
716    {
717        return false;
718    }
719
720    if (SearchStrEx(name, "standard", 0, false) != INFINITE)
721    {
722        return false;
723    }
724
725    return true;
726#endif
727}
728
729
730// Server スナップショットの初期化
731void InitServerSnapshot(SERVER *s)
732{
733    // 引数チェック
734    if (s == NULL)
735    {
736        return;
737    }
738
739    if (s->Cedar->Bridge)
740    {
741        return;
742    }
743
744    if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
745    {
746        return;
747    }
748
749    s->SnapshotLogger = NewLog(CE_SNAPSHOT_DIR_NAME, CE_SNAPSHOT_PREFIX, LOG_SWITCH_MONTH);
750    s->LastSnapshotTime = SystemTime64();
751    s->HaltSnapshot = false;
752    s->SnapshotHaltEvent = NewEvent();
753    s->SnapshotThread = NewThread(ServerSnapshotThread, s);
754    s->SnapshotInited = true;
755}
756
757// Server スナップショットの解放
758void FreeServerSnapshot(SERVER *s)
759{
760    // 引数チェック
761    if (s == NULL)
762    {
763        return;
764    }
765    if (s->SnapshotInited == false)
766    {
767        return;
768    }
769
770    s->HaltSnapshot = true;
771    Set(s->SnapshotHaltEvent);
772
773    WaitThread(s->SnapshotThread, INFINITE);
774    ReleaseThread(s->SnapshotThread);
775
776    FreeLog(s->SnapshotLogger);
777    ReleaseEvent(s->SnapshotHaltEvent);
778}
779
780// スナップショットをバッファに書き出す
781BUF *ServerSnapshotToBuf(SERVER_SNAPSHOT *t)
782{
783    BUF *b = NewBuf();
784    char tmp[MAX_SIZE * 3];
785    char tmp2[MAX_SIZE];
786    UCHAR hash[SHA1_SIZE];
787    UCHAR hash2[SHA1_SIZE];
788    UINT i;
789    // 引数チェック
790    if (t == NULL)
791    {
792        return NULL;
793    }
794
795    WriteBufLine(b, "------------------------------------------------------");
796    WriteBufLine(b, "[RECORD_INFO]");
797
798    GetDateTimeStr64(tmp2, sizeof(tmp2), SystemToLocal64(t->DateTime));
799    Format(tmp, sizeof(tmp), "DATETIME: %s", tmp2);
800    WriteBufLine(b, tmp);
801
802    IPToStr(tmp2, sizeof(tmp2), &t->ServerIp);
803    Format(tmp, sizeof(tmp), "SERVER_IP: %s", tmp2);
804    WriteBufLine(b, tmp);
805
806    Format(tmp, sizeof(tmp), "SERVER_HOSTNAME: %s", t->ServerHostname);
807    WriteBufLine(b, tmp);
808
809    Format(tmp, sizeof(tmp), "SERVER_PRODUCT: %s", t->ServerProduct);
810    WriteBufLine(b, tmp);
811
812    Format(tmp, sizeof(tmp), "SERVER_VERSION: %s", t->ServerVersion);
813    WriteBufLine(b, tmp);
814
815    Format(tmp, sizeof(tmp), "SERVER_BUILD: %s", t->ServerBuild);
816    WriteBufLine(b, tmp);
817
818    Format(tmp, sizeof(tmp), "SERVER_OS: %s", t->ServerOs);
819    WriteBufLine(b, tmp);
820
821    Format(tmp, sizeof(tmp), "SERVER_LICENSE_ID: %I64u", t->ServerLicenseId);
822    WriteBufLine(b, tmp);
823
824    if (t->ServerLicenseExpires != 0)
825    {
826        GetDateTimeStr64(tmp2, sizeof(tmp2), SystemToLocal64(t->ServerLicenseExpires));
827    }
828    else
829    {
830        StrCpy(tmp2, sizeof(tmp2), "None");
831    }
832    Format(tmp, sizeof(tmp), "SERVER_LICENSE_EXPIRES: %s", tmp2);
833    WriteBufLine(b, tmp);
834
835    Format(tmp, sizeof(tmp), "SERVER_TYPE: %u", t->ServerType);
836    WriteBufLine(b, tmp);
837
838    GetDateTimeStr64(tmp2, sizeof(tmp), SystemToLocal64(t->ServerStartupDatetime));
839    Format(tmp, sizeof(tmp), "SERVER_STARTUP_DATETIME: %s", tmp2);
840    WriteBufLine(b, tmp);
841
842    Format(tmp, sizeof(tmp), "NUMBER_OF_CLUSTER_NODES: %u", t->NumClusterNodes);
843    WriteBufLine(b, tmp);
844
845    Format(tmp, sizeof(tmp), "NUMBER_OF_HUBS: %u", LIST_NUM(t->HubList));
846    WriteBufLine(b, tmp);
847
848    for (i = 0;i < LIST_NUM(t->HubList);i++)
849    {
850        HUB_SNAPSHOT *h = LIST_DATA(t->HubList, i);
851        Format(tmp, sizeof(tmp), "[HUB%u]", i);
852        WriteBufLine(b, tmp);
853
854        Format(tmp, sizeof(tmp), "HUB_NAME: %s", h->HubName);
855        WriteBufLine(b, tmp);
856
857        Format(tmp, sizeof(tmp), "HUB_STATUS: %s",
858            h->HubStatus ? "Online" : "Offline");
859        WriteBufLine(b, tmp);
860
861        Format(tmp, sizeof(tmp), "HUB_MAX_SESSIONS_CLIENT: %u",
862            h->HubMaxSessionsClient);
863        WriteBufLine(b, tmp);
864
865        Format(tmp, sizeof(tmp), "HUB_MAX_SESSIONS_BRIDGE: %u",
866            h->HubMaxSessionsBridge);
867        WriteBufLine(b, tmp);
868    }
869
870    // ハッシュ計算
871    HashSha1(hash, b->Buf, b->Size);
872    HashSha1(hash2, hash, sizeof(hash));
873
874    WriteBufLine(b, "[DIGITAL_SIGNATURE]");
875    BinToStr(tmp2, sizeof(tmp2), hash2, sizeof(hash2));
876    Format(tmp, sizeof(tmp), "SIGNATURE: %s", tmp2);
877    WriteBufLine(b, tmp);
878
879    SeekBuf(b, 0, 0);
880
881    return b;
882}
883
884// スナップショットのログを書き込む
885void WriteServerSnapshotLog(SERVER *s, SERVER_SNAPSHOT *t)
886{
887    BUF *b;
888    LOG *g;
889    // 引数チェック
890    if (s == NULL || t == NULL)
891    {
892        return;
893    }
894
895    b = ServerSnapshotToBuf(t);
896    if (b == NULL)
897    {
898        return;
899    }
900
901    g = s->SnapshotLogger;
902
903    WriteMultiLineLog(g, b);
904
905    FreeBuf(b);
906}
907
908// Server スナップショットスレッド
909void ServerSnapshotThread(THREAD *t, void *param)
910{
911    SERVER *s;
912    UINT64 last_check_license = 0;
913    LICENSE_STATUS license;
914    // 引数チェック
915    if (t == NULL || param == NULL)
916    {
917        return;
918    }
919
920    s = (SERVER *)param;
921
922    Zero(&license, sizeof(license));
923
924    while (true)
925    {
926        UINT64 now;
927        if (s->HaltSnapshot)
928        {
929            break;
930        }
931
932        if (last_check_license == 0 || (last_check_license + (UINT64)(CE_SNAPSHOT_POLLING_INTERVAL_LICENSE)) <= Tick64())
933        {
934            last_check_license = Tick64();
935
936            LiParseCurrentLicenseStatus(s->LicenseSystem, &license);
937        }
938
939        if (license.CarrierEdition)
940        {
941            now = SystemTime64();
942
943            if ((s->LastSnapshotTime / CE_SNAPSHOT_INTERVAL) !=
944                (now / CE_SNAPSHOT_INTERVAL))
945            {
946                SERVER_SNAPSHOT t;
947                if (MakeServerSnapshot(s, 0, &t))
948                {
949                    s->LastSnapshotTime = now;
950                    WriteServerSnapshotLog(s, &t);
951
952                    FreeSnapshot(&t);
953                }
954            }
955        }
956
957        Wait(s->SnapshotHaltEvent, CE_SNAPSHOT_POLLING_INTERVAL);
958    }
959}
960
961// Server のスナップショットの保存
962bool MakeServerSnapshot(SERVER *s, UINT64 now, SERVER_SNAPSHOT *t)
963{
964    LICENSE_STATUS license;
965    OS_INFO *os = GetOsInfo();
966    CEDAR *cedar;
967    HUB **hubs;
968    UINT i, num_hubs;
969    // 引数チェック
970    if (s == NULL || t == NULL)
971    {
972        return false;
973    }
974    if (now == 0)
975    {
976        now = SystemTime64();
977    }
978
979    cedar = s->Cedar;
980
981    if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
982    {
983        return false;
984    }
985
986    Zero(&license, sizeof(license));
987    LiParseCurrentLicenseStatus(s->LicenseSystem, &license);
988
989    if (license.CarrierEdition == false)
990    {
991        return false;
992    }
993
994    now = (now / CE_SNAPSHOT_INTERVAL) * CE_SNAPSHOT_INTERVAL;
995
996    t->DateTime = now;
997    GetMachineIp(&t->ServerIp);
998    GetMachineName(t->ServerHostname, sizeof(t->ServerHostname));
999    StrCpy(t->ServerProduct, sizeof(t->ServerProduct), license.EditionStr);
1000    t->ServerLicenseId = license.SystemId;
1001    t->ServerLicenseExpires = license.Expires;
1002    t->ServerType = s->ServerType;
1003    if (t->ServerType == SERVER_TYPE_FARM_CONTROLLER)
1004    {
1005        LockList(s->FarmMemberList);
1006        {
1007            t->NumClusterNodes = LIST_NUM(s->FarmMemberList);
1008        }
1009        UnlockList(s->FarmMemberList);
1010    }
1011
1012    StrCpy(t->ServerVersion, sizeof(t->ServerVersion), s->Cedar->VerString);
1013    StrCpy(t->ServerBuild, sizeof(t->ServerBuild), s->Cedar->BuildInfo);
1014    Format(t->ServerOs, sizeof(t->ServerOs),
1015        "%s %s %s",
1016        os->OsVendorName, os->OsProductName, os->OsVersion);
1017
1018    t->ServerStartupDatetime = s->StartTime;
1019
1020    LockList(cedar->HubList);
1021    {
1022        num_hubs = LIST_NUM(cedar->HubList);
1023        hubs = ZeroMalloc(sizeof(HUB *) * num_hubs);
1024
1025        for (i = 0;i < num_hubs;i++)
1026        {
1027            HUB *h = LIST_DATA(cedar->HubList, i);
1028            hubs[i] = h;
1029
1030            AddRef(h->ref);
1031        }
1032    }
1033    UnlockList(cedar->HubList);
1034
1035    t->HubList = NewListFast(NULL);
1036
1037    for (i = 0;i < num_hubs;i++)
1038    {
1039        HUB *h = hubs[i];
1040        UINT client, bridge;
1041        HUB_SNAPSHOT *sn;
1042
1043        client = GetHubAdminOption(h, "max_sessions_client");
1044        bridge = GetHubAdminOption(h, "max_sessions_bridge");
1045
1046        sn = ZeroMalloc(sizeof(HUB_SNAPSHOT));
1047        sn->HubMaxSessionsClient = client;
1048        sn->HubMaxSessionsBridge = bridge;
1049        StrCpy(sn->HubName, sizeof(sn->HubName), h->Name);
1050        sn->HubStatus = h->Offline ? false : true;
1051
1052        Insert(t->HubList, sn);
1053
1054        ReleaseHub(h);
1055    }
1056
1057    Free(hubs);
1058
1059    return true;
1060}
1061
1062// スナップショットの解放
1063void FreeSnapshot(SERVER_SNAPSHOT *t)
1064{
1065    UINT i;
1066    // 引数チェック
1067    if (t == NULL)
1068    {
1069        return;
1070    }
1071
1072    for (i = 0;i < LIST_NUM(t->HubList);i++)
1073    {
1074        HUB_SNAPSHOT *h = LIST_DATA(t->HubList, i);
1075
1076        Free(h);
1077    }
1078
1079    ReleaseList(t->HubList);
1080
1081    Zero(t, sizeof(SERVER_SNAPSHOT));
1082}
1083
1084// サーバーの現在のライセンスステータスを取得する
1085void SiGetServerLicenseStatus(SERVER *s, LICENSE_STATUS *st)
1086{
1087    // 引数チェック
1088    if (s == NULL || st == NULL)
1089    {
1090        return;
1091    }
1092
1093    if (s->LicenseSystem == NULL || s->LicenseSystem->Status == NULL)
1094    {
1095        Zero(st, sizeof(LICENSE_STATUS));
1096        return;
1097    }
1098
1099    Copy(st, s->LicenseSystem->Status, sizeof(LICENSE_STATUS));
1100}
1101
1102// サーバー製品名を取得する
1103void GetServerProductName(SERVER *s, char *name, UINT size)
1104{
1105    char *cpu;
1106    // 引数チェック
1107    if (s == NULL || name == NULL)
1108    {
1109        return;
1110    }
1111
1112    GetServerProductNameInternal(s, name, size);
1113
1114#ifdef  CPU_64
1115    cpu = " (64 bit)";
1116#else   // CPU_64
1117    cpu = " (32 bit)";
1118#endif  // CPU_64
1119
1120    StrCat(name, size, cpu);
1121}
1122void GetServerProductNameInternal(SERVER *s, char *name, UINT size)
1123{
1124    // 引数チェック
1125    if (s == NULL || name == NULL)
1126    {
1127        return;
1128    }
1129
1130#ifdef  BETA_NUMBER
1131    if (s->Cedar->Bridge)
1132    {
1133        StrCpy(name, size, CEDAR_BRIDGE_STR);
1134    }
1135    else
1136    {
1137        StrCpy(name, size, CEDAR_BETA_SERVER);
1138    }
1139    return;
1140#else   // BETA_NUMBER
1141    if (s->Cedar->Bridge)
1142    {
1143        StrCpy(name, size, CEDAR_BRIDGE_STR);
1144    }
1145    else
1146    {
1147        LICENSE_STATUS st;
1148
1149        LiParseCurrentLicenseStatus(s->LicenseSystem, &st);
1150
1151        StrCpy(name, size, st.EditionStr);
1152    }
1153#endif  // BETA_NUMBER
1154}
1155
1156// ログファイル列挙を結合する
1157void AdjoinEnumLogFile(LIST *o, LIST *src)
1158{
1159    UINT i;
1160    // 引数チェック
1161    if (o == NULL || src == NULL)
1162    {
1163        return;
1164    }
1165
1166    for (i = 0;i < LIST_NUM(src);i++)
1167    {
1168        LOG_FILE *f = LIST_DATA(src, i);
1169
1170        Insert(o, Clone(f, sizeof(LOG_FILE)));
1171    }
1172}
1173
1174// 指定した名前のログファイルが列挙リストに入っているかどうか確認する
1175bool CheckLogFileNameFromEnumList(LIST *o, char *name, char *server_name)
1176{
1177    LOG_FILE t;
1178    // 引数チェック
1179    if (o == NULL || name == NULL || server_name == NULL)
1180    {
1181        return false;
1182    }
1183
1184    Zero(&t, sizeof(t));
1185    StrCpy(t.Path, sizeof(t.Path), name);
1186    StrCpy(t.ServerName, sizeof(t.ServerName), server_name);
1187
1188    if (Search(o, &t) == NULL)
1189    {
1190        return false;
1191    }
1192
1193    return true;
1194}
1195
1196// ログファイル列挙を解放する
1197void FreeEnumLogFile(LIST *o)
1198{
1199    UINT i;
1200    // 引数チェック
1201    if (o == NULL)
1202    {
1203        return;
1204    }
1205
1206    for (i = 0;i < LIST_NUM(o);i++)
1207    {
1208        LOG_FILE *f = LIST_DATA(o, i);
1209
1210        Free(f);
1211    }
1212
1213    ReleaseList(o);
1214}
1215
1216// 仮想 HUB に関連するログファイルを列挙する (サーバー管理者の場合はすべて列挙する)
1217LIST *EnumLogFile(char *hubname)
1218{
1219    char exe_dir[MAX_PATH];
1220    char tmp[MAX_PATH];
1221    LIST *o = NewListFast(CmpLogFile);
1222    DIRLIST *dir;
1223
1224    if (StrLen(hubname) == 0)
1225    {
1226        hubname = NULL;
1227    }
1228
1229    GetExeDir(exe_dir, sizeof(exe_dir));
1230
1231    // server_log の下を列挙する
1232    if (hubname == NULL)
1233    {
1234        EnumLogFileDir(o, "server_log");
1235    }
1236
1237    // packet_log の下を列挙する
1238    Format(tmp, sizeof(tmp), "%s/packet_log", exe_dir);
1239    dir = EnumDir(tmp);
1240    if (dir != NULL)
1241    {
1242        UINT i;
1243        for (i = 0;i < dir->NumFiles;i++)
1244        {
1245            DIRENT *e = dir->File[i];
1246
1247            if (e->Folder)
1248            {
1249                char dir_name[MAX_PATH];
1250
1251                if (hubname == NULL || StrCmpi(hubname, e->FileName) == 0)
1252                {
1253                    Format(dir_name, sizeof(dir_name), "packet_log/%s", e->FileName);
1254                    EnumLogFileDir(o, dir_name);
1255                }
1256            }
1257        }
1258
1259        FreeDir(dir);
1260    }
1261
1262    // security_log の下を列挙する
1263    Format(tmp, sizeof(tmp), "%s/security_log", exe_dir);
1264    dir = EnumDir(tmp);
1265    if (dir != NULL)
1266    {
1267        UINT i;
1268        for (i = 0;i < dir->NumFiles;i++)
1269        {
1270            DIRENT *e = dir->File[i];
1271
1272            if (e->Folder)
1273            {
1274                char dir_name[MAX_PATH];
1275
1276                if (hubname == NULL || StrCmpi(hubname, e->FileName) == 0)
1277                {
1278                    Format(dir_name, sizeof(dir_name), "security_log/%s", e->FileName);
1279                    EnumLogFileDir(o, dir_name);
1280                }
1281            }
1282        }
1283
1284        FreeDir(dir);
1285    }
1286
1287    return o;
1288}
1289
1290// 指定した名前のディレクトリのログファイルを列挙する
1291void EnumLogFileDir(LIST *o, char *dirname)
1292{
1293    UINT i;
1294    char exe_dir[MAX_PATH];
1295    char dir_full_path[MAX_PATH];
1296    DIRLIST *dir;
1297    // 引数チェック
1298    if (o == NULL || dirname == NULL)
1299    {
1300        return;
1301    }
1302
1303    GetExeDir(exe_dir, sizeof(exe_dir));
1304    Format(dir_full_path, sizeof(dir_full_path), "%s/%s", exe_dir, dirname);
1305
1306    dir = EnumDir(dir_full_path);
1307    if (dir == NULL)
1308    {
1309        return;
1310    }
1311
1312    for (i = 0;i < dir->NumFiles;i++)
1313    {
1314        DIRENT *e = dir->File[i];
1315
1316        if (e->Folder == false && e->FileSize > 0)
1317        {
1318            char full_path[MAX_PATH];
1319            char file_path[MAX_PATH];
1320
1321            Format(file_path, sizeof(file_path), "%s/%s", dirname, e->FileName);
1322            Format(full_path, sizeof(full_path), "%s/%s", exe_dir, file_path);
1323
1324            if (EndWith(file_path, ".log"))
1325            {
1326                LOG_FILE *f = ZeroMalloc(sizeof(LOG_FILE));
1327
1328                StrCpy(f->Path, sizeof(f->Path), file_path);
1329                f->FileSize = (UINT)(MIN(e->FileSize, 0xffffffffUL));
1330                f->UpdatedTime = e->UpdateDate;
1331
1332                GetMachineName(f->ServerName, sizeof(f->ServerName));
1333
1334                Insert(o, f);
1335            }
1336        }
1337    }
1338
1339    FreeDir(dir);
1340}
1341
1342// ログファイルリストエントリ比較
1343int CmpLogFile(void *p1, void *p2)
1344{
1345    LOG_FILE *f1, *f2;
1346    UINT i;
1347    if (p1 == NULL || p2 == NULL)
1348    {
1349        return 0;
1350    }
1351    f1 = *(LOG_FILE **)p1;
1352    f2 = *(LOG_FILE **)p2;
1353    if (f1 == NULL || f2 == NULL)
1354    {
1355        return 0;
1356    }
1357
1358    i = StrCmpi(f1->Path, f2->Path);
1359    if (i != 0)
1360    {
1361        return i;
1362    }
1363
1364    return StrCmpi(f1->ServerName, f2->ServerName);
1365}
1366
1367// サーバーの Caps を取得する
1368UINT GetServerCapsInt(SERVER *s, char *name)
1369{
1370    CAPSLIST t;
1371    UINT ret;
1372    // 引数チェック
1373    if (s == NULL || name == NULL)
1374    {
1375        return 0;
1376    }
1377
1378    Zero(&t, sizeof(t));
1379    GetServerCaps(s, &t);
1380
1381    ret = GetCapsInt(&t, name);
1382
1383    return ret;
1384}
1385bool GetServerCapsBool(SERVER *s, char *name)
1386{
1387    return (GetServerCapsInt(s, name) == 0) ? false : true;
1388}
1389
1390// サーバーの Caps キャッシュの初期化
1391void InitServerCapsCache(SERVER *s)
1392{
1393    // 引数チェック
1394    if (s == NULL)
1395    {
1396        return;
1397    }
1398
1399    s->CapsCacheLock = NewLock();
1400    s->CapsListCache = NULL;
1401}
1402
1403// サーバーの Caps キャッシュの解放
1404void FreeServerCapsCache(SERVER *s)
1405{
1406    // 引数チェック
1407    if (s == NULL)
1408    {
1409        return;
1410    }
1411
1412    if (s->CapsListCache != NULL)
1413    {
1414        FreeCapsList(s->CapsListCache);
1415        s->CapsListCache = NULL;
1416    }
1417    DeleteLock(s->CapsCacheLock);
1418}
1419
1420// サーバーの Caps キャッシュの廃棄
1421void DestroyServerCapsCache(SERVER *s)
1422{
1423    // 引数チェック
1424    if (s == NULL)
1425    {
1426        return;
1427    }
1428
1429    Lock(s->CapsCacheLock);
1430    {
1431        if (s->CapsListCache != NULL)
1432        {
1433            FreeCapsList(s->CapsListCache);
1434            s->CapsListCache = NULL;
1435        }
1436    }
1437    Unlock(s->CapsCacheLock);
1438}
1439
1440// このサーバーの Caps リストを取得する
1441void GetServerCaps(SERVER *s, CAPSLIST *t)
1442{
1443    // 引数チェック
1444    if (s == NULL || t == NULL)
1445    {
1446        return;
1447    }
1448
1449    Lock(s->CapsCacheLock);
1450    {
1451        if (s->CapsListCache == NULL)
1452        {
1453            s->CapsListCache = ZeroMalloc(sizeof(CAPSLIST));
1454            GetServerCapsMain(s, s->CapsListCache);
1455        }
1456
1457        Copy(t, s->CapsListCache, sizeof(s->CapsListCache));
1458    }
1459    Unlock(s->CapsCacheLock);
1460}
1461
1462// サーバーの Caps 取得メイン
1463void GetServerCapsMain(SERVER *s, CAPSLIST *t)
1464{
1465    // 引数チェック
1466    if (s == NULL || t == NULL)
1467    {
1468        return;
1469    }
1470
1471    // 初期化
1472    InitCapsList(t);
1473
1474    // 最大 Ethernet パケットサイズ
1475    AddCapsInt(t, "i_max_packet_size", MAX_PACKET_SIZE);
1476
1477    if (s->Cedar->Bridge == false)
1478    {
1479        LICENSE_STATUS st;
1480        UINT max_sessions, max_clients, max_bridges, max_user_creations;
1481
1482        LiParseCurrentLicenseStatus(s->LicenseSystem, &st);
1483
1484        max_clients = st.NumClientLicense;
1485        max_bridges = st.NumBridgeLicense;
1486        max_sessions = st.MaxSessions;
1487        max_user_creations = st.NumUserLicense;
1488
1489        // 最大仮想 HUB 数
1490        AddCapsInt(t, "i_max_hubs", st.MaxHubs);
1491
1492        // 最大同時接続セッション数
1493        AddCapsInt(t, "i_max_sessions", max_sessions);
1494
1495        // 最大作成可能ユーザー数
1496        AddCapsInt(t, "i_max_user_creation", max_user_creations);
1497
1498        // 最大クライアント数
1499        AddCapsInt(t, "i_max_clients", max_clients);
1500
1501        // 最大ブリッジ数
1502        AddCapsInt(t, "i_max_bridges", max_bridges);
1503
1504        if (s->ServerType != SERVER_TYPE_FARM_MEMBER)
1505        {
1506            // 登録可能な最大ユーザー数 / 仮想 HUB
1507            AddCapsInt(t, "i_max_users_per_hub", MAX_USERS);
1508
1509            // 登録可能な最大グループ数 / 仮想 HUB
1510            AddCapsInt(t, "i_max_groups_per_hub", MAX_GROUPS);
1511
1512            // 登録可能な最大アクセスリスト数 / 仮想 HUB
1513            AddCapsInt(t, "i_max_access_lists", MAX_ACCESSLISTS);
1514        }
1515        else
1516        {
1517            // 登録可能な最大ユーザー数 / 仮想 HUB
1518            AddCapsInt(t, "i_max_users_per_hub", 0);
1519
1520            // 登録可能な最大グループ数 / 仮想 HUB
1521            AddCapsInt(t, "i_max_groups_per_hub", 0);
1522
1523            // 登録可能な最大アクセスリスト数 / 仮想 HUB
1524            AddCapsInt(t, "i_max_access_lists", 0);
1525        }
1526
1527        // 多重ログインに関するポリシー
1528        AddCapsBool(t, "b_support_limit_multilogin", true);
1529
1530        // QoS / VoIP
1531        AddCapsBool(t, "b_support_qos", true);
1532    }
1533    else
1534    {
1535        // 最大仮想 HUB 数
1536        AddCapsInt(t, "i_max_hubs", 0);
1537
1538        // 最大同時接続セッション数
1539        AddCapsInt(t, "i_max_sessions", 0);
1540
1541        // 最大クライアント数
1542        AddCapsInt(t, "i_max_clients", 0);
1543
1544        // 最大ブリッジ数
1545        AddCapsInt(t, "i_max_bridges", 0);
1546
1547        // 登録可能な最大ユーザー数 / 仮想 HUB
1548        AddCapsInt(t, "i_max_users_per_hub", 0);
1549
1550        // 登録可能な最大グループ数 / 仮想 HUB
1551        AddCapsInt(t, "i_max_groups_per_hub", 0);
1552
1553        // 登録可能な最大アクセスリスト数 / 仮想 HUB
1554        AddCapsInt(t, "i_max_access_lists", 0);
1555
1556        // QoS / VoIP
1557        AddCapsBool(t, "b_support_qos", true);
1558
1559        // syslog
1560        AddCapsBool(t, "b_support_syslog", true);
1561    }
1562
1563    // syslog は使用不可
1564    AddCapsBool(t, "b_support_syslog", false);
1565
1566    // クラスタ内仮想 HUB の種類の変更が禁止されている
1567    AddCapsBool(t, "b_cluster_hub_type_fixed", true);
1568
1569    // MAC アドレステーブル最大サイズ / 仮想 HUB
1570    AddCapsInt(t, "i_max_mac_tables", MAX_MAC_TABLES);
1571
1572    // IP アドレステーブル最大サイズ / 仮想 HUB
1573    AddCapsInt(t, "i_max_ip_tables", MAX_IP_TABLES);
1574
1575    // SecureNAT 機能が使用できる
1576    AddCapsBool(t, "b_support_securenat", true);
1577
1578    if (s->ServerType != SERVER_TYPE_STANDALONE)
1579    {
1580        AddCapsBool(t, "b_virtual_nat_disabled", true);
1581    }
1582
1583    // NAT テーブル最大サイズ / 仮想 HUB
1584    AddCapsInt(t, "i_max_secnat_tables", NAT_MAX_SESSIONS);
1585
1586    // カスケード接続
1587    if (s->ServerType == SERVER_TYPE_STANDALONE)
1588    {
1589        AddCapsBool(t, "b_support_cascade", true);
1590    }
1591    else
1592    {
1593        AddCapsBool(t, "b_support_cascade", false);
1594    }
1595
1596    if (s->Cedar->Bridge)
1597    {
1598        // ブリッジ モード
1599        AddCapsBool(t, "b_bridge", true);
1600    }
1601    else if (s->ServerType == SERVER_TYPE_STANDALONE)
1602    {
1603        // スタンドアロン モード
1604        AddCapsBool(t, "b_standalone", true);
1605    }
1606    else if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
1607    {
1608        // クラスタ コントローラ モード
1609        AddCapsBool(t, "b_cluster_controller", true);
1610    }
1611    else
1612    {
1613        // クラスタ メンバ モード
1614        AddCapsBool(t, "b_cluster_member", true);
1615    }
1616
1617    // 仮想 HUB の設定変更が可能である
1618    AddCapsBool(t, "b_support_config_hub", s->ServerType != SERVER_TYPE_FARM_MEMBER &&
1619        s->Cedar->Bridge == false);
1620
1621    // VPN クライアントが接続可能である
1622    AddCapsBool(t, "b_vpn_client_connect", s->Cedar->Bridge == false ? true : false);
1623
1624    // 外部認証サーバーは使用不可
1625    AddCapsBool(t, "b_support_radius", false);
1626
1627    // ローカル ブリッジ機能が使用できる
1628    AddCapsBool(t, "b_local_bridge", IsBridgeSupported());
1629
1630    if (OS_IS_WINDOWS(GetOsInfo()->OsType))
1631    {
1632        // パケットキャプチャドライバが未インストール
1633        AddCapsBool(t, "b_must_install_pcap", IsEthSupported() == false ? true : false);
1634    }
1635    else
1636    {
1637        // Linux 版ではドライバはインストール済みとする
1638        AddCapsBool(t, "b_must_install_pcap", false);
1639    }
1640
1641    if (IsBridgeSupported())
1642    {
1643        // tun/tap が使用可能 (Linux のみ)
1644        AddCapsBool(t, "b_tap_supported", GetOsInfo()->OsType == OSTYPE_LINUX ? true : false);
1645    }
1646
1647    // カスケード接続
1648    if (s->ServerType == SERVER_TYPE_STANDALONE)
1649    {
1650        AddCapsBool(t, "b_support_cascade", true);
1651    }
1652    else
1653    {
1654        AddCapsBool(t, "b_support_cascade", false);
1655    }
1656
1657    // カスケード接続時のサーバー認証が使用できる
1658    AddCapsBool(t, "b_support_cascade_cert", true);
1659
1660    // ログファイル設定の変更ができる
1661    AddCapsBool(t, "b_support_config_log", s->ServerType != SERVER_TYPE_FARM_MEMBER);
1662
1663    // ログファイルの自動削除が使用可能である
1664    AddCapsBool(t, "b_support_autodelete", true);
1665
1666    // config 操作が使用可能である
1667    AddCapsBool(t, "b_support_config_rw", true);
1668
1669    // 仮想 HUB ごとの属性が設定可能である
1670    AddCapsBool(t, "b_support_hub_admin_option", true);
1671
1672    // カスケード接続でクライアント証明書が設定可能である
1673    AddCapsBool(t, "b_support_cascade_client_cert", true);
1674
1675    // 仮想 HUB を隠すことができる
1676    AddCapsBool(t, "b_support_hide_hub", true);
1677
1678    // 統合管理
1679    AddCapsBool(t, "b_support_cluster_admin", true);
1680
1681    if (s->Cedar->Bridge == false)
1682    {
1683        LICENSE_STATUS status;
1684        // 仮想レイヤ 3 スイッチ機能が使える
1685        AddCapsBool(t, "b_support_layer3", true);
1686
1687        AddCapsInt(t, "i_max_l3_sw", MAX_NUM_L3_SWITCH);
1688        AddCapsInt(t, "i_max_l3_if", MAX_NUM_L3_IF);
1689        AddCapsInt(t, "i_max_l3_table", MAX_NUM_L3_TABLE);
1690
1691        LiParseCurrentLicenseStatus(s->LicenseSystem, &status);
1692
1693        if (status.AllowEnterpriseFunction || s->ServerType != SERVER_TYPE_STANDALONE)
1694        {
1695            // クラスタの一部として動作できる
1696            AddCapsBool(t, "b_support_cluster", true);
1697        }
1698        else
1699        {
1700            // クラスタとして動作できない
1701            AddCapsBool(t, "b_support_cluster", false);
1702        }
1703    }
1704    else
1705    {
1706        AddCapsBool(t, "b_support_layer3", false);
1707
1708        AddCapsInt(t, "i_max_l3_sw", 0);
1709        AddCapsInt(t, "i_max_l3_if", 0);
1710        AddCapsInt(t, "i_max_l3_table", 0);
1711
1712        AddCapsBool(t, "b_support_cluster", false);
1713    }
1714
1715    if (s->ServerType != SERVER_TYPE_FARM_MEMBER && s->Cedar->Bridge == false)
1716    {
1717        // CRL をサポート
1718        AddCapsBool(t, "b_support_crl", true);
1719    }
1720
1721    // AC は非サポート
1722    AddCapsBool(t, "b_support_ac", false);
1723
1724    // ログ ファイルのダウンロードをサポート
1725    AddCapsBool(t, "b_support_read_log", true);
1726
1727    // カスケード接続の名前の変更が可能である
1728    AddCapsBool(t, "b_support_rename_cascade", true);
1729
1730    // ライセンス管理は不可能
1731    AddCapsBool(t, "b_support_license", false);
1732
1733    if (s->Cedar->Beta)
1734    {
1735        // ベータ版
1736        AddCapsBool(t, "b_beta_version", true);
1737    }
1738
1739    // ローカルブリッジにネットワーク接続の名前表示をサポート
1740#ifdef  OS_WIN32
1741    if (IsBridgeSupported() && IsNt() && GetOsInfo()->OsType >= OSTYPE_WINDOWS_2000_PROFESSIONAL)
1742    {
1743        AddCapsBool(t, "b_support_network_connection_name", true);
1744    }
1745#else   // OS_WIN32
1746    if (IsBridgeSupported() && EthIsInterfaceDescriptionSupportedUnix())
1747    {
1748        AddCapsBool(t, "b_support_network_connection_name", true);
1749    }
1750#endif  // OS_WIN32
1751
1752    // MAC アドレスフィルタリングをサポート
1753    AddCapsBool(t, "b_support_check_mac", true);
1754
1755    // TCP コネクションの状態チェックをサポート
1756    AddCapsBool(t, "b_support_check_tcp_state", true);
1757
1758    // Radius 認証は使用不可
1759    AddCapsBool(t, "b_support_radius_retry_interval_and_several_servers", false);
1760
1761    // MAC アドレステーブルでタグ付き VLAN の ID を管理できる
1762    AddCapsBool(t, "b_support_vlan", true);
1763
1764    // 仮想 HUB 拡張オプションをサポート
1765    if ((s->Cedar->Bridge == false) &&
1766        (s->ServerType == SERVER_TYPE_STANDALONE || s->ServerType == SERVER_TYPE_FARM_CONTROLLER))
1767    {
1768        AddCapsBool(t, "b_support_hub_ext_options", true);
1769    }
1770    else
1771    {
1772        AddCapsBool(t, "b_support_hub_ext_options", false);
1773    }
1774
1775    // セキュリティポリシー バージョン 3.0 をサポート
1776    AddCapsBool(t, "b_support_policy_ver_3", true);
1777
1778    // IPv6 アクセスリストをサポート
1779    AddCapsBool(t, "b_support_ipv6_acl", true);
1780
1781    // アクセスリストで遅延・ジッタ・パケットロスの設定をサポート
1782    AddCapsBool(t, "b_support_ex_acl", true);
1783
1784    // アクセスリストでグループ名による指定をサポート
1785    AddCapsBool(t, "b_support_acl_group", true);
1786
1787    // IPv6 接続元 IP 制限リストをサポート
1788    AddCapsBool(t, "b_support_ipv6_ac", true);
1789
1790    // タグ付き VLAN パケット透過設定ツールをサポート
1791    AddCapsBool(t, "b_support_eth_vlan", (OS_IS_WINDOWS_NT(GetOsType()) && GET_KETA(GetOsType(), 100) >= 2));
1792
1793    // 仮想 HUB への VPN 接続時のメッセージ表示機能をサポート
1794    AddCapsBool(t, "b_support_msg", true);
1795
1796    // VPN3
1797    AddCapsBool(t, "b_vpn3", true);
1798
1799    // オープンソース版
1800    AddCapsBool(t, "b_gpl", true);
1801}
1802
1803// SYSLOG_SETTING
1804void InRpcSysLogSetting(SYSLOG_SETTING *t, PACK *p)
1805{
1806    // 引数チェック
1807    if (t == NULL || p == NULL)
1808    {
1809        return;
1810    }
1811
1812    Zero(t, sizeof(SYSLOG_SETTING));
1813    t->SaveType = PackGetInt(p, "SaveType");
1814    t->Port = PackGetInt(p, "Port");
1815    PackGetStr(p, "Hostname", t->Hostname, sizeof(t->Hostname));
1816}
1817void OutRpcSysLogSetting(PACK *p, SYSLOG_SETTING *t)
1818{
1819    // 引数チェック
1820    if (t == NULL || p == NULL)
1821    {
1822        return;
1823    }
1824
1825    PackAddInt(p, "SaveType", t->SaveType);
1826    PackAddInt(p, "Port", t->Port);
1827    PackAddStr(p, "Hostname", t->Hostname);
1828}
1829
1830// CAPSLIST
1831void InitCapsList(CAPSLIST *t)
1832{
1833    // 引数チェック
1834    if (t == NULL)
1835    {
1836        return;
1837    }
1838
1839    Zero(t, sizeof(CAPSLIST));
1840    t->CapsList = NewListFast(NULL);
1841}
1842void InRpcCapsList(CAPSLIST *t, PACK *p)
1843{
1844    UINT i;
1845    // 引数チェック
1846    if (t == NULL || p == NULL)
1847    {
1848        return;
1849    }
1850
1851    Zero(t, sizeof(CAPSLIST));
1852    t->CapsList = NewListFast(CompareCaps);
1853
1854    for (i = 0;i < LIST_NUM(p->elements);i++)
1855    {
1856        ELEMENT *e = LIST_DATA(p->elements, i);
1857
1858        if (StartWith(e->name, "caps_") && e->type == VALUE_INT && e->num_value == 1)
1859        {
1860            CAPS *c = NewCaps(e->name + 5, e->values[0]->IntValue);
1861            Insert(t->CapsList, c);
1862        }
1863    }
1864}
1865void OutRpcCapsList(PACK *p, CAPSLIST *t)
1866{
1867    UINT i;
1868    // 引数チェック
1869    if (t == NULL || p == NULL)
1870    {
1871        return;
1872    }
1873
1874    for (i = 0;i < LIST_NUM(t->CapsList);i++)
1875    {
1876        char tmp[MAX_SIZE];
1877        CAPS *c = LIST_DATA(t->CapsList, i);
1878
1879        Format(tmp, sizeof(tmp), "caps_%s", c->Name);
1880        PackAddInt(p, tmp, c->Value);
1881    }
1882}
1883void FreeRpcCapsList(CAPSLIST *t)
1884{
1885    UINT i;
1886    // 引数チェック
1887    if (t == NULL)
1888    {
1889        return;
1890    }
1891
1892    for (i = 0;i < LIST_NUM(t->CapsList);i++)
1893    {
1894        CAPS *c = LIST_DATA(t->CapsList, i);
1895
1896        FreeCaps(c);
1897    }
1898
1899    ReleaseList(t->CapsList);
1900}
1901
1902// Caps リストに bool 型を追加
1903void AddCapsBool(CAPSLIST *caps, char *name, bool b)
1904{
1905    CAPS *c;
1906    // 引数チェック
1907    if (caps == NULL || name == NULL)
1908    {
1909        return;
1910    }
1911
1912    c = NewCaps(name, b == false ? 0 : 1);
1913    AddCaps(caps, c);
1914}
1915
1916// Caps リストに int 型を追加
1917void AddCapsInt(CAPSLIST *caps, char *name, UINT i)
1918{
1919    CAPS *c;
1920    // 引数チェック
1921    if (caps == NULL || name == NULL)
1922    {
1923        return;
1924    }
1925
1926    c = NewCaps(name, i);
1927    AddCaps(caps, c);
1928}
1929
1930// Caps リストから int 型を取得
1931UINT GetCapsInt(CAPSLIST *caps, char *name)
1932{
1933    CAPS *c;
1934    // 引数チェック
1935    if (caps == NULL || name == NULL)
1936    {
1937        return 0;
1938    }
1939
1940    c = GetCaps(caps, name);
1941    if (c == NULL)
1942    {
1943        return 0;
1944    }
1945
1946    return c->Value;
1947}
1948
1949// Caps リストから bool 型を取得
1950bool GetCapsBool(CAPSLIST *caps, char *name)
1951{
1952    CAPS *c;
1953    // 引数チェック
1954    if (caps == NULL || name == NULL)
1955    {
1956        return false;
1957    }
1958
1959    c = GetCaps(caps, name);
1960    if (c == NULL)
1961    {
1962        return false;
1963    }
1964
1965    return c->Value == 0 ? false : true;
1966}
1967
1968// Caps リストの解放
1969void FreeCapsList(CAPSLIST *caps)
1970{
1971    UINT i;
1972    // 引数チェック
1973    if (caps == NULL)
1974    {
1975        return;
1976    }
1977
1978    for (i = 0;i < LIST_NUM(caps->CapsList);i++)
1979    {
1980        CAPS *c = LIST_DATA(caps->CapsList, i);
1981
1982        FreeCaps(c);
1983    }
1984
1985    ReleaseList(caps->CapsList);
1986    Free(caps);
1987}
1988
1989// Caps の取得
1990CAPS *GetCaps(CAPSLIST *caps, char *name)
1991{
1992    UINT i;
1993    // 引数チェック
1994    if (caps == NULL || name == NULL)
1995    {
1996        return NULL;
1997    }
1998
1999    for (i = 0;i < LIST_NUM(caps->CapsList);i++)
2000    {
2001        CAPS *c = LIST_DATA(caps->CapsList, i);
2002
2003        if (StrCmpi(c->Name, name) == 0)
2004        {
2005            return c;
2006        }
2007    }
2008
2009    return NULL;
2010}
2011
2012// Caps の追加
2013void AddCaps(CAPSLIST *caps, CAPS *c)
2014{
2015    // 引数チェック
2016    if (caps == NULL || c == NULL)
2017    {
2018        return;
2019    }
2020
2021    Insert(caps->CapsList, c);
2022}
2023
2024// Caps の比較
2025int CompareCaps(void *p1, void *p2)
2026{
2027    CAPS *c1, *c2;
2028    if (p1 == NULL || p2 == NULL)
2029    {
2030        return 0;
2031    }
2032    c1 = *(CAPS **)p1;
2033    c2 = *(CAPS **)p2;
2034    if (c1 == NULL || c2 == NULL)
2035    {
2036        return 0;
2037    }
2038
2039    return StrCmpi(c1->Name, c2->Name);
2040}
2041
2042// Caps リストの作成
2043CAPSLIST *NewCapsList()
2044{
2045    CAPSLIST *caps = ZeroMalloc(sizeof(CAPSLIST));
2046
2047    caps->CapsList = NewListFast(CompareCaps);
2048
2049    return caps;
2050}
2051
2052// Caps の解放
2053void FreeCaps(CAPS *c)
2054{
2055    // 引数チェック
2056    if (c == NULL)
2057    {
2058        return;
2059    }
2060
2061    Free(c->Name);
2062    Free(c);
2063}
2064
2065// Caps の作成
2066CAPS *NewCaps(char *name, UINT value)
2067{
2068    CAPS *c;
2069    // 引数チェック
2070    if (name == NULL)
2071    {
2072        return NULL;
2073    }
2074
2075    c = ZeroMalloc(sizeof(CAPS));
2076    c->Name = CopyStr(name);
2077    c->Value = value;
2078
2079    return c;
2080}
2081
2082// 現在の接続数と重みから得点を計算する
2083UINT SiCalcPoint(SERVER *s, UINT num, UINT weight)
2084{
2085    UINT server_max_sessions = SERVER_MAX_SESSIONS;
2086    if (s == NULL)
2087    {
2088        return 0;
2089    }
2090    if (weight == 0)
2091    {
2092        weight = 100;
2093    }
2094
2095    server_max_sessions = GetServerCapsInt(s, "i_max_sessions");
2096
2097    return (UINT)(((double)server_max_sessions -
2098        MIN((double)num * 100.0 / (double)weight, (double)server_max_sessions))
2099        * (double)FARM_BASE_POINT / (double)server_max_sessions);
2100}
2101
2102// サーバー得点の取得
2103UINT SiGetPoint(SERVER *s)
2104{
2105    UINT num_session;
2106    // 引数チェック
2107    if (s == NULL)
2108    {
2109        return 0;
2110    }
2111
2112    num_session = Count(s->Cedar->CurrentSessions);
2113
2114    return SiCalcPoint(s, num_session, s->Weight);
2115}
2116
2117// デフォルトの証明書を生成する
2118void SiGenerateDefualtCert(X **server_x, K **server_k)
2119{
2120    X *x;
2121    K *private_key, *public_key;
2122    NAME *name;
2123    char tmp[MAX_SIZE];
2124    wchar_t cn[MAX_SIZE];
2125    // 引数チェック
2126    if (server_x == NULL || server_k == NULL)
2127    {
2128        return;
2129    }
2130
2131    // 鍵ペアの作成
2132    RsaGen(&private_key, &public_key, 1024);
2133
2134    // ホスト名の取得
2135    StrCpy(tmp, sizeof(tmp), "server.softether.vpn");
2136    GetMachineName(tmp, sizeof(tmp));
2137
2138    StrToUni(cn, sizeof(cn), tmp);
2139    name = NewName(cn, L"Default Random Certification", L"VPN Server",
2140        L"JP", NULL, NULL);
2141    x = NewRootX(public_key, private_key, name, MAX(GetDaysUntil2038(), SERVER_DEFAULT_CERT_DAYS), NULL);
2142
2143    *server_x = x;
2144    *server_k = private_key;
2145
2146    FreeName(name);
2147
2148    FreeK(public_key);
2149}
2150
2151// サーバー証明書をデフォルトにする
2152void SiInitDefaultServerCert(SERVER *s)
2153{
2154    X *x = NULL;
2155    K *k = NULL;
2156    // 引数チェック
2157    if (s == NULL)
2158    {
2159        return;
2160    }
2161
2162    // サーバー証明書と秘密鍵を生成する
2163    SiGenerateDefualtCert(&x, &k);
2164
2165    // 設定する
2166    SetCedarCert(s->Cedar, x, k);
2167
2168    FreeX(x);
2169    FreeK(k);
2170}
2171
2172// 暗号化アルゴリズム名をデフォルトにする
2173void SiInitCipherName(SERVER *s)
2174{
2175    // 引数チェック
2176    if (s == NULL)
2177    {
2178        return;
2179    }
2180
2181    SetCedarCipherList(s->Cedar, SERVER_DEFAULT_CIPHER_NAME);
2182}
2183
2184// リスナーリストを初期化する
2185void SiInitListenerList(SERVER *s)
2186{
2187    // 引数チェック
2188    if (s == NULL)
2189    {
2190        return;
2191    }
2192
2193    SiLockListenerList(s);
2194    {
2195        // デフォルト ポートとして 443, 992, 5555 の 3 つのポートを登録する
2196        SiAddListener(s, 443, true);
2197        SiAddListener(s, 992, true);
2198        SiAddListener(s, 5555, true);
2199    }
2200    SiUnlockListenerList(s);
2201}
2202
2203// リスナーを削除する
2204bool SiDeleteListener(SERVER *s, UINT port)
2205{
2206    SERVER_LISTENER *e;
2207    // 引数チェック
2208    if (s == NULL || port == 0)
2209    {
2210        return false;
2211    }
2212
2213    e = SiGetListener(s, port);
2214    if (e == NULL)
2215    {
2216        return false;
2217    }
2218
2219    // まだ動作中であれば停止する
2220    SiDisableListener(s, port);
2221
2222    if (e->Listener != NULL)
2223    {
2224        ReleaseListener(e->Listener);
2225    }
2226
2227    Delete(s->ServerListenerList, e);
2228    Free(e);
2229
2230    return true;
2231}
2232
2233// SERVER_LISTENER を比較する
2234int CompareServerListener(void *p1, void *p2)
2235{
2236    SERVER_LISTENER *s1, *s2;
2237    if (p1 == NULL || p2 == NULL)
2238    {
2239        return 0;
2240    }
2241    s1 = *(SERVER_LISTENER **)p1;
2242    s2 = *(SERVER_LISTENER **)p2;
2243    if (s1 == NULL || s2 == NULL)
2244    {
2245        return 0;
2246    }
2247
2248    if (s1->Port > s2->Port)
2249    {
2250        return 1;
2251    }
2252    else if (s1->Port < s2->Port)
2253    {
2254        return -1;
2255    }
2256    else
2257    {
2258        return 0;
2259    }
2260}
2261
2262// リスナーを停止する
2263bool SiDisableListener(SERVER *s, UINT port)
2264{
2265    SERVER_LISTENER *e;
2266    // 引数チェック
2267    if (s == NULL || port == 0)
2268    {
2269        return false;
2270    }
2271
2272    // リスナーを取得する
2273    e = SiGetListener(s, port);
2274    if (e == NULL)
2275    {
2276        return false;
2277    }
2278
2279    if (e->Enabled == false || e->Listener == NULL)
2280    {
2281        // 停止中である
2282        return true;
2283    }
2284
2285    // リスナーを停止する
2286    StopListener(e->Listener);
2287
2288    // リスナーを解放する
2289    ReleaseListener(e->Listener);
2290    e->Listener = NULL;
2291
2292    e->Enabled = false;
2293
2294    return true;
2295}
2296
2297// リスナーを開始する
2298bool SiEnableListener(SERVER *s, UINT port)
2299{
2300    SERVER_LISTENER *e;
2301    // 引数チェック
2302    if (s == NULL || port == 0)
2303    {
2304        return false;
2305    }
2306
2307    // リスナーを取得する
2308    e = SiGetListener(s, port);
2309    if (e == NULL)
2310    {
2311        return false;
2312    }
2313
2314    if (e->Enabled)
2315    {
2316        // すでに開始されている
2317        return true;
2318    }
2319
2320    // リスナーを作成する
2321    e->Listener = NewListener(s->Cedar, LISTENER_TCP, e->Port);
2322    if (e->Listener == NULL)
2323    {
2324        // 失敗
2325        return false;
2326    }
2327
2328    e->Enabled = true;
2329
2330    return true;
2331}
2332
2333// リスナーを取得する
2334SERVER_LISTENER *SiGetListener(SERVER *s, UINT port)
2335{
2336    UINT i;
2337    // 引数チェック
2338    if (s == NULL || port == 0)
2339    {
2340        return NULL;
2341    }
2342
2343    for (i = 0;i < LIST_NUM(s->ServerListenerList);i++)
2344    {
2345        SERVER_LISTENER *e = LIST_DATA(s->ServerListenerList, i);
2346        if (e->Port == port)
2347        {
2348            return e;
2349        }
2350    }
2351
2352    return NULL;
2353}
2354
2355// リスナーを追加する
2356bool SiAddListener(SERVER *s, UINT port, bool enabled)
2357{
2358    SERVER_LISTENER *e;
2359    UINT i;
2360    // 引数チェック
2361    if (s == NULL || port == 0)
2362    {
2363        return false;
2364    }
2365
2366    // 既存のリスナーが存在していないかどうかチェックする
2367    for (i = 0;i < LIST_NUM(s->ServerListenerList);i++)
2368    {
2369        e = LIST_DATA(s->ServerListenerList, i);
2370        if (e->Port == port)
2371        {
2372            // すでに存在する
2373            return false;
2374        }
2375    }
2376
2377    // 新しいリスナーを初期化して登録する
2378    e = ZeroMalloc(sizeof(SERVER_LISTENER));
2379    e->Enabled = enabled;
2380    e->Port = port;
2381
2382    if (e->Enabled)
2383    {
2384        // リスナーを作成する
2385        e->Listener = NewListener(s->Cedar, LISTENER_TCP, e->Port);
2386    }
2387
2388    Insert(s->ServerListenerList, e);
2389
2390    return true;
2391}
2392
2393// リスナーリストをロックする
2394void SiLockListenerList(SERVER *s)
2395{
2396    // 引数チェック
2397    if (s == NULL)
2398    {
2399        return;
2400    }
2401
2402    LockList(s->ServerListenerList);
2403}
2404
2405// リスナーリストのロックを解除する
2406void SiUnlockListenerList(SERVER *s)
2407{
2408    // 引数チェック
2409    if (s == NULL)
2410    {
2411        return;
2412    }
2413
2414    UnlockList(s->ServerListenerList);
2415}
2416
2417// Bridge の初期化
2418void SiInitBridge(SERVER *s)
2419{
2420    HUB *h;
2421    HUB_OPTION o;
2422    HUB_LOG g;
2423    // 引数チェック
2424    if (s == NULL)
2425    {
2426        return;
2427    }
2428
2429    Zero(&o, sizeof(o));
2430    o.MaxSession = 0;
2431
2432    h = NewHub(s->Cedar, SERVER_DEFAULT_BRIDGE_NAME, &o);
2433    AddHub(s->Cedar, h);
2434
2435    h->Offline = true;
2436    SetHubOnline(h);
2437
2438    // ログ設定
2439    SiSetDefaultLogSetting(&g);
2440    SetHubLogSetting(h, &g);
2441
2442    ReleaseHub(h);
2443}
2444
2445// デフォルトの仮想 HUB を作成する
2446void SiInitDefaultHubList(SERVER *s)
2447{
2448    HUB *h;
2449    HUB_OPTION o;
2450    HUB_LOG g;
2451    // 引数チェック
2452    if (s == NULL)
2453    {
2454        return;
2455    }
2456
2457    Zero(&o, sizeof(o));
2458    o.MaxSession = 0;
2459    o.VlanTypeId = MAC_PROTO_TAGVLAN;
2460    o.NoIPv6DefaultRouterInRAWhenIPv6 = true;
2461    o.ManageOnlyPrivateIP = true;
2462    o.ManageOnlyLocalUnicastIPv6 = true;
2463    o.NoMacAddressLog = true;
2464
2465    h = NewHub(s->Cedar, s->Cedar->Bridge == false ? SERVER_DEFAULT_HUB_NAME : SERVER_DEFAULT_BRIDGE_NAME, &o);
2466    h->CreatedTime = SystemTime64();
2467    AddHub(s->Cedar, h);
2468
2469    if (s->Cedar->Bridge)
2470    {
2471        // パスワードを乱数にする
2472        Rand(h->HashedPassword, sizeof(h->HashedPassword));
2473        Rand(h->SecurePassword, sizeof(h->SecurePassword));
2474    }
2475
2476    h->Offline = true;
2477    SetHubOnline(h);
2478
2479    // ログ設定
2480    SiSetDefaultLogSetting(&g);
2481    SetHubLogSetting(h, &g);
2482
2483    {
2484        UINT i;
2485        for (i = 0;i < 0;i++)
2486        {
2487            char tmp[MAX_SIZE];
2488            USER *u;
2489            sprintf(tmp, "user%u", i);
2490            AcLock(h);
2491            u = NewUser(tmp, L"test", L"", AUTHTYPE_ANONYMOUS, NULL);
2492            AcAddUser(h, u);
2493            ReleaseUser(u);
2494            AcUnlock(h);
2495        }
2496    }
2497
2498    ReleaseHub(h);
2499}
2500
2501// ログ設定をデフォルトにする
2502void SiSetDefaultLogSetting(HUB_LOG *g)
2503{
2504    // 引数チェック
2505    if (g == NULL)
2506    {
2507        return;
2508    }
2509
2510    Zero(g, sizeof(HUB_LOG));
2511    g->SaveSecurityLog = true;
2512    g->SecurityLogSwitchType = LOG_SWITCH_DAY;
2513    g->SavePacketLog = false;
2514    g->PacketLogSwitchType = LOG_SWITCH_DAY;
2515    g->PacketLogConfig[PACKET_LOG_TCP_CONN] =
2516        g->PacketLogConfig[PACKET_LOG_DHCP] = PACKET_LOG_HEADER;
2517}
2518
2519// テスト
2520void SiTest(SERVER *s)
2521{
2522#if 0
2523    USER *u;
2524    USERGROUP *g;
2525    HUB *h;
2526    LINK *k;
2527    CLIENT_OPTION o;
2528    CLIENT_AUTH a;
2529    ACCESS *ac;
2530    X *x;
2531    // 引数チェック
2532    if (s == NULL)
2533    {
2534        return;
2535    }
2536
2537    h = GetHub(s->Cedar, SERVER_DEFAULT_HUB_NAME);
2538    if (h == NULL)
2539    {
2540        return;
2541    }
2542
2543    // ユーザーを作成する
2544    g = NewGroup("test_group", L"テスト グループ", L"テストです。");
2545    AcAddGroup(h, g);
2546
2547    u = NewUser("test", L"テスト", L"はむです", AUTHTYPE_ANONYMOUS, NULL);
2548    AcAddUser(h, u);
2549    JoinUserToGroup(u, g);
2550    ReleaseUser(u);
2551
2552    u = NewUser("anonymous", L"匿名ユーザー", L"ソフトイーサ株式会社", AUTHTYPE_ANONYMOUS, NULL);
2553    AcAddUser(h, u);
2554    JoinUserToGroup(u, g);
2555    ReleaseUser(u);
2556
2557    u = NewUser("password", L"パスワードユーザー", L"ソフトイーサ株式会社", AUTHTYPE_PASSWORD, NewPasswordAuthData("password", "microsoft"));
2558    AcAddUser(h, u);
2559    ReleaseUser(u);
2560
2561    x = FileToX("mayaqua.cer");
2562    u = NewUser("usercert", L"ユーザー証明書テストユーザー", L"ソフトイーサ株式会社", AUTHTYPE_USERCERT, NewUserCertAuthData(x));
2563    AcAddUser(h, u);
2564    ReleaseUser(u);
2565    FreeX(x);
2566
2567    u = NewUser("rootcert", L"ルート証明書テストユーザー", L"ソフトイーサ株式会社", AUTHTYPE_ROOTCERT, NewRootCertAuthData(NULL, NULL));
2568    AcAddUser(h, u);
2569    ReleaseUser(u);
2570
2571    u = NewUser("*", L"*", L"すべて", AUTHTYPE_RADIUS, NewRadiusAuthData(L""));
2572    AcAddUser(h, u);
2573    ReleaseUser(u);
2574
2575    ReleaseGroup(g);
2576
2577    // Radius サーバーを設定する
2578    SetRadiusServer(h, "dc.sec.softether.co.jp", RADIUS_DEFAULT_PORT, "microsoft");
2579
2580    // HUB 間リンクを作成する
2581    Zero(&o, sizeof(o));
2582    UniStrCpy(o.AccountName, sizeof(o.AccountName), L"テスト リンク");
2583    o.MaxConnection = 8;
2584    o.NumRetry = INFINITE;
2585    o.UseEncrypt = true;
2586    StrCpy(o.HubName, sizeof(o.HubName), "TEST_HUB");
2587    o.Port = 443;
2588    StrCpy(o.Hostname, sizeof(o.Hostname), "ts.softether.co.jp");
2589
2590    Zero(&a, sizeof(a));
2591    a.AuthType = CLIENT_AUTHTYPE_ANONYMOUS;
2592    StrCpy(a.Username, sizeof(a.Username), "anonymous_test");
2593
2594    k = NewLink(s->Cedar, h, &o, &a, GetDefaultPolicy());
2595    StartLink(k);
2596
2597    ReleaseLink(k);
2598
2599    // 証明書を追加する
2600    x = FileToX("root.cer");
2601    AddRootCert(h, x);
2602    FreeX(x);
2603
2604    // アクセスリストを追加する
2605    ac = ZeroMalloc(sizeof(ACCESS));
2606    ac->Id = 1;
2607    UniStrCpy(ac->Note, sizeof(ac->Note), L"アクセスリストのテスト");
2608    ac->Active = true;
2609    ac->Priority = 3;
2610    ac->Discard = true;
2611    ac->SrcIpAddress = 0x12345678;
2612    ac->SrcSubnetMask = 0xffffffff;
2613    ac->DestIpAddress = 0x36547894;
2614    ac->DestSubnetMask = 0xffffffff;
2615    ac->Protocol = IP_PROTO_TCP;
2616    StrCpy(ac->SrcUsername, 0, "yagi");
2617    StrCpy(ac->DestUsername, 0, "neko");
2618    AddAccessList(h, ac);
2619    Free(ac);
2620
2621    ReleaseHub(h);
2622#endif
2623}
2624
2625// 初期コンフィグレーションを設定する
2626void SiLoadInitialConfiguration(SERVER *s)
2627{
2628    RPC_KEEP k;
2629    // 引数チェック
2630    if (s == NULL)
2631    {
2632        return;
2633    }
2634
2635    // 自動保存間隔関係
2636    s->AutoSaveConfigSpan = SERVER_FILE_SAVE_INTERVAL_DEFAULT;
2637
2638    s->Weight = FARM_DEFAULT_WEIGHT;
2639
2640    // KEEP 関係
2641    Zero(&k, sizeof(k));
2642    k.UseKeepConnect = true;
2643    k.KeepConnectPort = 80;
2644    StrCpy(k.KeepConnectHost, sizeof(k.KeepConnectHost), CLIENT_DEFAULT_KEEPALIVE_HOST);
2645    k.KeepConnectInterval = KEEP_INTERVAL_DEFAULT * 1000;
2646    k.KeepConnectProtocol = CONNECTION_UDP;
2647
2648    Lock(s->Keep->lock);
2649    {
2650        KEEP *keep = s->Keep;
2651        keep->Enable = k.UseKeepConnect;
2652        keep->Server = true;
2653        StrCpy(keep->ServerName, sizeof(keep->ServerName), k.KeepConnectHost);
2654        keep->ServerPort = k.KeepConnectPort;
2655        keep->UdpMode = k.KeepConnectProtocol;
2656        keep->Interval = k.KeepConnectInterval;
2657    }
2658    Unlock(s->Keep->lock);
2659
2660    // パスワードを初期化する
2661    Hash(s->HashedPassword, "", 0, true);
2662
2663    // 暗号化アルゴリズム名をデフォルトにする
2664    SiInitCipherName(s);
2665
2666    // サーバー証明書をデフォルトにする
2667    SiInitDefaultServerCert(s);
2668
2669    // リスナーリストをデフォルト設定する
2670    SiInitListenerList(s);
2671
2672    // デフォルト HUB の作成
2673    SiInitDefaultHubList(s);
2674
2675    s->Eraser = NewEraser(s->Logger, 0);
2676}
2677
2678// コンフィグレーションファイルを読み込む (メイン)
2679bool SiLoadConfigurationFileMain(SERVER *s, FOLDER *root)
2680{
2681    // 引数チェック
2682    if (s == NULL || root == NULL)
2683    {
2684        return false;
2685    }
2686
2687    return SiLoadConfigurationCfg(s, root);
2688}
2689
2690// コンフィグレーションファイルを読み込む
2691bool SiLoadConfigurationFile(SERVER *s)
2692{
2693    // 引数チェック
2694    bool ret = false;
2695    FOLDER *root;
2696    if (s == NULL)
2697    {
2698        return false;
2699    }
2700
2701    s->CfgRw = NewCfgRw(&root,
2702        s->Cedar->Bridge == false ? SERVER_CONFIG_FILE_NAME : BRIDGE_CONFIG_FILE_NAME);
2703
2704    if (server_reset_setting)
2705    {
2706        CfgDeleteFolder(root);
2707        root = NULL;
2708        server_reset_setting = false;
2709    }
2710
2711    if (root == NULL)
2712    {
2713        return false;
2714    }
2715
2716    ret = SiLoadConfigurationFileMain(s, root);
2717
2718    CfgDeleteFolder(root);
2719
2720    return ret;
2721}
2722
2723// コンフィグレーション初期化
2724void SiInitConfiguration(SERVER *s)
2725{
2726    // 引数チェック
2727    if (s == NULL)
2728    {
2729        return;
2730    }
2731
2732    // Ethernet 初期化
2733    InitEth();
2734
2735    s->AutoSaveConfigSpan = SERVER_FILE_SAVE_INTERVAL_DEFAULT;
2736
2737    SLog(s->Cedar, "LS_LOAD_CONFIG_1");
2738    if (SiLoadConfigurationFile(s) == false)
2739    {
2740        SLog(s->Cedar, "LS_LOAD_CONFIG_3");
2741        SiLoadInitialConfiguration(s);
2742
2743        server_reset_setting = false;
2744    }
2745    else
2746    {
2747        SLog(s->Cedar, "LS_LOAD_CONFIG_2");
2748    }
2749
2750    // Linux における arp_filter
2751    if (GetOsInfo()->OsType == OSTYPE_LINUX)
2752    {
2753        if (s->NoLinuxArpFilter == false)
2754        {
2755            SetLinuxArpFilter();
2756        }
2757    }
2758
2759    // 保存スレッド作成
2760    SLog(s->Cedar, "LS_INIT_SAVE_THREAD", s->AutoSaveConfigSpan / 1000);
2761    s->SaveHaltEvent = NewEvent();
2762    s->SaveThread = NewThread(SiSaverThread, s);
2763}
2764
2765// サーバー設定を CFG から読み込む
2766bool SiLoadConfigurationCfg(SERVER *s, FOLDER *root)
2767{
2768    FOLDER *f1, *f2, *f3, *f4, *f5, *f6;
2769    // 引数チェック
2770    if (s == NULL || root == NULL)
2771    {
2772        return false;
2773    }
2774
2775    f1 = CfgGetFolder(root, "ServerConfiguration");
2776    f2 = CfgGetFolder(root, "VirtualHUB");
2777    f3 = CfgGetFolder(root, "ListenerList");
2778    f4 = CfgGetFolder(root, "LocalBridgeList");
2779    f5 = CfgGetFolder(root, "VirtualLayer3SwitchList");
2780    f6 = CfgGetFolder(root, "LicenseManager");
2781
2782    if (f1 == NULL)
2783    {
2784        SLog(s->Cedar, "LS_BAD_CONFIG");
2785        return false;
2786    }
2787
2788    s->ConfigRevision = CfgGetInt(root, "ConfigRevision");
2789
2790    if (s->Cedar->Bridge == false && f6 != NULL)
2791    {
2792        if (GetServerCapsBool(s, "b_support_license"))
2793        {
2794            SiLoadLicenseManager(s, f6);
2795        }
2796    }
2797
2798    DestroyServerCapsCache(s);
2799
2800    SiLoadServerCfg(s, f1);
2801
2802    if (s->ServerType != SERVER_TYPE_FARM_MEMBER)
2803    {
2804        SiLoadHubs(s, f2);
2805    }
2806
2807    SiLoadListeners(s, f3);
2808
2809    if (f4 != NULL)
2810    {
2811        SiLoadLocalBridges(s, f4);
2812    }
2813
2814    if (s->Cedar->Bridge == false && f5 != NULL)
2815    {
2816        SiLoadL3Switchs(s, f5);
2817    }
2818
2819    return true;
2820}
2821
2822// リスナー設定を書き出す
2823void SiWriteListenerCfg(FOLDER *f, SERVER_LISTENER *r)
2824{
2825    // 引数チェック
2826    if (f == NULL || r == NULL)
2827    {
2828        return;
2829    }
2830
2831    CfgAddBool(f, "Enabled", r->Enabled);
2832    CfgAddInt(f, "Port", r->Port);
2833}
2834
2835// リスナー設定を読み込む
2836void SiLoadListenerCfg(SERVER *s, FOLDER *f)
2837{
2838    bool enable;
2839    UINT port;
2840    // 引数チェック
2841    if (s == NULL || f == NULL)
2842    {
2843        return;
2844    }
2845
2846    enable = CfgGetBool(f, "Enabled");
2847    port = CfgGetInt(f, "Port");
2848
2849    if (port == 0)
2850    {
2851        return;
2852    }
2853
2854    SiAddListener(s, port, enable);
2855}
2856
2857// リスナー一覧を読み込む
2858void SiLoadListeners(SERVER *s, FOLDER *f)
2859{
2860    TOKEN_LIST *t;
2861    UINT i;
2862    // 引数チェック
2863    if (s == NULL || f == NULL)
2864    {
2865        return;
2866    }
2867
2868    t = CfgEnumFolderToTokenList(f);
2869    for (i = 0;i < t->NumTokens;i++)
2870    {
2871        FOLDER *ff = CfgGetFolder(f, t->Token[i]);
2872        if (ff != NULL)
2873        {
2874            SiLoadListenerCfg(s, ff);
2875        }
2876    }
2877    FreeToken(t);
2878}
2879
2880// リスナー一覧を書き出す
2881void SiWriteListeners(FOLDER *f, SERVER *s)
2882{
2883    // 引数チェック
2884    if (f == NULL || s == NULL)
2885    {
2886        return;
2887    }
2888
2889    LockList(s->ServerListenerList);
2890    {
2891        UINT i;
2892        for (i = 0;i < LIST_NUM(s->ServerListenerList);i++)
2893        {
2894            SERVER_LISTENER *r = LIST_DATA(s->ServerListenerList, i);
2895            char name[MAX_SIZE];
2896            Format(name, sizeof(name), "Listener%u", i);
2897            SiWriteListenerCfg(CfgCreateFolder(f, name), r);
2898        }
2899    }
2900    UnlockList(s->ServerListenerList);
2901}
2902
2903// ブリッジを書き出す
2904void SiWriteLocalBridgeCfg(FOLDER *f, LOCALBRIDGE *br)
2905{
2906    // 引数チェック
2907    if (f == NULL || br == NULL)
2908    {
2909        return;
2910    }
2911
2912    CfgAddStr(f, "DeviceName", br->DeviceName);
2913    CfgAddStr(f, "HubName", br->HubName);
2914    CfgAddBool(f, "NoPromiscuousMode", br->Local);
2915    CfgAddBool(f, "MonitorMode", br->Monitor);
2916    CfgAddBool(f, "FullBroadcastMode", br->FullBroadcast);
2917
2918    if (OS_IS_UNIX(GetOsInfo()->OsType))
2919    {
2920        CfgAddBool(f, "TapMode", br->TapMode);
2921
2922        if (br->TapMode)
2923        {
2924            char tmp[MAX_SIZE];
2925            MacToStr(tmp, sizeof(tmp), br->TapMacAddress);
2926            CfgAddStr(f, "TapMacAddress", tmp);
2927        }
2928    }
2929}
2930
2931// ブリッジ一覧を書き出す
2932void SiWriteLocalBridges(FOLDER *f, SERVER *s)
2933{
2934    // 引数チェック
2935    if (s == NULL || f == NULL)
2936    {
2937        return;
2938    }
2939
2940    LockList(s->Cedar->LocalBridgeList);
2941    {
2942        UINT i;
2943        for (i = 0;i < LIST_NUM(s->Cedar->LocalBridgeList);i++)
2944        {
2945            LOCALBRIDGE *br = LIST_DATA(s->Cedar->LocalBridgeList, i);
2946            char name[MAX_SIZE];
2947
2948            Format(name, sizeof(name), "LocalBridge%u", i);
2949            SiWriteLocalBridgeCfg(CfgCreateFolder(f, name), br);
2950        }
2951    }
2952    UnlockList(s->Cedar->LocalBridgeList);
2953}
2954
2955// ブリッジを読み込む
2956void SiLoadLocalBridgeCfg(SERVER *s, FOLDER *f)
2957{
2958    char hub[MAX_SIZE];
2959    char nic[MAX_SIZE];
2960    bool tapmode = false;
2961    UCHAR tapaddr[6];
2962    // 引数チェック
2963    if (s == NULL || f == NULL)
2964    {
2965        return;
2966    }
2967
2968    Zero(hub, sizeof(hub));
2969    Zero(nic, sizeof(nic));
2970
2971    CfgGetStr(f, "HubName", hub, sizeof(hub));
2972    CfgGetStr(f, "DeviceName", nic, sizeof(nic));
2973
2974    if (IsEmptyStr(hub) || IsEmptyStr(nic))
2975    {
2976        return;
2977    }
2978
2979    if (OS_IS_UNIX(GetOsInfo()->OsType))
2980    {
2981        if (CfgGetBool(f, "TapMode"))
2982        {
2983            char tmp[MAX_SIZE];
2984            tapmode = true;
2985            Zero(tapaddr, sizeof(tapaddr));
2986            if (CfgGetStr(f, "TapMacAddress", tmp, sizeof(tmp)))
2987            {
2988                BUF *b;
2989                b = StrToBin(tmp);
2990                if (b != NULL && b->Size == 6)
2991                {
2992                    Copy(tapaddr, b->Buf, sizeof(tapaddr));
2993                }
2994                FreeBuf(b);
2995            }
2996        }
2997    }
2998
2999    AddLocalBridge(s->Cedar, hub, nic, CfgGetBool(f, "NoPromiscuousMode"), CfgGetBool(f, "MonitorMode"),
3000        tapmode, tapaddr, CfgGetBool(f, "FullBroadcastMode"));
3001}
3002
3003// ブリッジ一覧を読み込む
3004void SiLoadLocalBridges(SERVER *s, FOLDER *f)
3005{
3006    TOKEN_LIST *t;
3007    UINT i;
3008    // 引数チェック
3009    if (s == NULL || f == NULL)
3010    {
3011        return;
3012    }
3013
3014    t = CfgEnumFolderToTokenList(f);
3015
3016    for (i = 0;i < t->NumTokens;i++)
3017    {
3018        char *name = t->Token[i];
3019
3020        SiLoadLocalBridgeCfg(s, CfgGetFolder(f, name));
3021    }
3022
3023    FreeToken(t);
3024}
3025
3026// サーバーの設定リビジョンをインクリメントする
3027void IncrementServerConfigRevision(SERVER *s)
3028{
3029    // 引数チェック
3030    if (s == NULL)
3031    {
3032        return;
3033    }
3034
3035    s->ConfigRevision++;
3036}
3037
3038// サーバー設定を CFG に書き出す
3039FOLDER *SiWriteConfigurationToCfg(SERVER *s)
3040{
3041    FOLDER *root;
3042    // 引数チェック
3043    if (s == NULL)
3044    {
3045        return NULL;
3046    }
3047
3048    root = CfgCreateFolder(NULL, TAG_ROOT);
3049
3050    CfgAddInt(root, "ConfigRevision", s->ConfigRevision);
3051
3052    SiWriteListeners(CfgCreateFolder(root, "ListenerList"), s);
3053
3054    SiWriteLocalBridges(CfgCreateFolder(root, "LocalBridgeList"), s);
3055
3056    SiWriteServerCfg(CfgCreateFolder(root, "ServerConfiguration"), s);
3057
3058    if (s->UpdatedServerType != SERVER_TYPE_FARM_MEMBER)
3059    {
3060        SiWriteHubs(CfgCreateFolder(root, "VirtualHUB"), s);
3061    }
3062
3063    if (s->Cedar->Bridge == false)
3064    {
3065        SiWriteL3Switchs(CfgCreateFolder(root, "VirtualLayer3SwitchList"), s);
3066
3067        if (GetServerCapsBool(s, "b_support_license"))
3068        {
3069            SiWriteLicenseManager(CfgCreateFolder(root, "LicenseManager"), s);
3070        }
3071    }
3072
3073    return root;
3074}
3075
3076// ポリシーの読み込み
3077void SiLoadPolicyCfg(POLICY *p, FOLDER *f)
3078{
3079    // 引数チェック
3080    if (f == NULL || p == NULL)
3081    {
3082        return;
3083    }
3084
3085    Zero(p, sizeof(POLICY));
3086
3087    // Ver 2
3088    p->Access = CfgGetBool(f, "Access");
3089    p->DHCPFilter = CfgGetBool(f, "DHCPFilter");
3090    p->DHCPNoServer = CfgGetBool(f, "DHCPNoServer");
3091    p->DHCPForce = CfgGetBool(f, "DHCPForce");
3092    p->NoBridge = CfgGetBool(f, "NoBridge");
3093    p->NoRouting = CfgGetBool(f, "NoRouting");
3094    p->CheckMac = CfgGetBool(f, "CheckMac");
3095    p->CheckIP = CfgGetBool(f, "CheckIP");
3096    p->ArpDhcpOnly = CfgGetBool(f, "ArpDhcpOnly");
3097    p->PrivacyFilter = CfgGetBool(f, "PrivacyFilter");
3098    p->NoServer = CfgGetBool(f, "NoServer");
3099    p->NoBroadcastLimiter = CfgGetBool(f, "NoBroadcastLimiter");
3100    p->MonitorPort = CfgGetBool(f, "MonitorPort");
3101    p->MaxConnection = CfgGetInt(f, "MaxConnection");
3102    p->TimeOut = CfgGetInt(f, "TimeOut");
3103    p->MaxMac = CfgGetInt(f, "MaxMac");
3104    p->MaxIP = CfgGetInt(f, "MaxIP");
3105    p->MaxUpload = CfgGetInt(f, "MaxUpload");
3106    p->MaxDownload = CfgGetInt(f, "MaxDownload");
3107    p->FixPassword = CfgGetBool(f, "FixPassword");
3108    p->MultiLogins = CfgGetInt(f, "MultiLogins");
3109    p->NoQoS = CfgGetBool(f, "NoQoS");
3110
3111    // Ver 3
3112    p->RSandRAFilter = CfgGetBool(f, "RSandRAFilter");
3113    p->RAFilter = CfgGetBool(f, "RAFilter");
3114    p->DHCPv6Filter = CfgGetBool(f, "DHCPv6Filter");
3115    p->DHCPv6NoServer = CfgGetBool(f, "DHCPv6NoServer");
3116    p->NoRoutingV6 = CfgGetBool(f, "NoRoutingV6");
3117    p->CheckIPv6 = CfgGetBool(f, "CheckIPv6");
3118    p->NoServerV6 = CfgGetBool(f, "NoServerV6");
3119    p->MaxIPv6 = CfgGetInt(f, "MaxIPv6");
3120    p->NoSavePassword = CfgGetBool(f, "NoSavePassword");
3121    p->AutoDisconnect = CfgGetInt(f, "AutoDisconnect");
3122    p->FilterIPv4 = CfgGetBool(f, "FilterIPv4");
3123    p->FilterIPv6 = CfgGetBool(f, "FilterIPv6");
3124    p->FilterNonIP = CfgGetBool(f, "FilterNonIP");
3125    p->NoIPv6DefaultRouterInRA = CfgGetBool(f, "NoIPv6DefaultRouterInRA");
3126    p->NoIPv6DefaultRouterInRAWhenIPv6 = CfgGetBool(f, "NoIPv6DefaultRouterInRAWhenIPv6");
3127    p->VLanId = CfgGetInt(f, "VLanId");
3128}
3129
3130// ポリシーの書き込み
3131void SiWritePolicyCfg(FOLDER *f, POLICY *p, bool cascade_mode)
3132{
3133    // 引数チェック
3134    if (f == NULL || p == NULL)
3135    {
3136        return;
3137    }
3138
3139    // Ver 2.0
3140    if (cascade_mode == false)
3141    {
3142        CfgAddBool(f, "Access", p->Access);
3143    }
3144
3145    CfgAddBool(f, "DHCPFilter", p->DHCPFilter);
3146    CfgAddBool(f, "DHCPNoServer", p->DHCPNoServer);
3147    CfgAddBool(f, "DHCPForce", p->DHCPForce);
3148
3149    if (cascade_mode == false)
3150    {
3151        CfgAddBool(f, "NoBridge", p->NoBridge);
3152        CfgAddBool(f, "NoRouting", p->NoRouting);
3153    }
3154
3155    CfgAddBool(f, "CheckMac", p->CheckMac);
3156    CfgAddBool(f, "CheckIP", p->CheckIP);
3157    CfgAddBool(f, "ArpDhcpOnly", p->ArpDhcpOnly);
3158
3159    if (cascade_mode == false)
3160    {
3161        CfgAddBool(f, "PrivacyFilter", p->PrivacyFilter);
3162    }
3163
3164    CfgAddBool(f, "NoServer", p->NoServer);
3165    CfgAddBool(f, "NoBroadcastLimiter", p->NoBroadcastLimiter);
3166
3167    if (cascade_mode == false)
3168    {
3169        CfgAddBool(f, "MonitorPort", p->MonitorPort);
3170        CfgAddInt(f, "MaxConnection", p->MaxConnection);
3171        CfgAddInt(f, "TimeOut", p->TimeOut);
3172    }
3173
3174    CfgAddInt(f, "MaxMac", p->MaxMac);
3175    CfgAddInt(f, "MaxIP", p->MaxIP);
3176    CfgAddInt(f, "MaxUpload", p->MaxUpload);
3177    CfgAddInt(f, "MaxDownload", p->MaxDownload);
3178
3179    if (cascade_mode == false)
3180    {
3181        CfgAddBool(f, "FixPassword", p->FixPassword);
3182        CfgAddInt(f, "MultiLogins", p->MultiLogins);
3183        CfgAddBool(f, "NoQoS", p->NoQoS);
3184    }
3185
3186    // Ver 3.0
3187    CfgAddBool(f, "RSandRAFilter", p->RSandRAFilter);
3188    CfgAddBool(f, "RAFilter", p->RAFilter);
3189    CfgAddBool(f, "DHCPv6Filter", p->DHCPv6Filter);
3190    CfgAddBool(f, "DHCPv6NoServer", p->DHCPv6NoServer);
3191
3192    if (cascade_mode == false)
3193    {
3194        CfgAddBool(f, "NoRoutingV6", p->NoRoutingV6);
3195    }
3196
3197    CfgAddBool(f, "CheckIPv6", p->CheckIPv6);
3198    CfgAddBool(f, "NoServerV6", p->NoServerV6);
3199    CfgAddInt(f, "MaxIPv6", p->MaxIPv6);
3200
3201    if (cascade_mode == false)
3202    {
3203        CfgAddBool(f, "NoSavePassword", p->NoSavePassword);
3204        CfgAddInt(f, "AutoDisconnect", p->AutoDisconnect);
3205    }
3206
3207    CfgAddBool(f, "FilterIPv4", p->FilterIPv4);
3208    CfgAddBool(f, "FilterIPv6", p->FilterIPv6);
3209    CfgAddBool(f, "FilterNonIP", p->FilterNonIP);
3210    CfgAddBool(f, "NoIPv6DefaultRouterInRA", p->NoIPv6DefaultRouterInRA);
3211    CfgAddBool(f, "NoIPv6DefaultRouterInRAWhenIPv6", p->NoIPv6DefaultRouterInRAWhenIPv6);
3212    CfgAddInt(f, "VLanId", p->VLanId);
3213}
3214
3215// 仮想 HUB のリンク情報の書き込み
3216void SiWriteHubLinkCfg(FOLDER *f, LINK *k)
3217{
3218    // 引数チェック
3219    if (f == NULL || k == NULL)
3220    {
3221        return;
3222    }
3223
3224    Lock(k->lock);
3225    {
3226        // オンライン
3227        CfgAddBool(f, "Online", k->Offline ? false : true);
3228
3229        // クライアントオプション
3230        CiWriteClientOption(CfgCreateFolder(f, "ClientOption"), k->Option);
3231
3232        // クライアント認証データ
3233        CiWriteClientAuth(CfgCreateFolder(f, "ClientAuth"), k->Auth);
3234
3235        // ポリシー
3236        if (k->Policy != NULL)
3237        {
3238            SiWritePolicyCfg(CfgCreateFolder(f, "Policy"), k->Policy, true);
3239        }
3240
3241        CfgAddBool(f, "CheckServerCert", k->CheckServerCert);
3242
3243        if (k->ServerCert != NULL)
3244        {
3245            BUF *b = XToBuf(k->ServerCert, false);
3246            CfgAddBuf(f, "ServerCert", b);
3247            FreeBuf(b);
3248        }
3249    }
3250    Unlock(k->lock);
3251}
3252
3253// リンク情報の読み込み
3254void SiLoadHubLinkCfg(FOLDER *f, HUB *h)
3255{
3256    bool online;
3257    CLIENT_OPTION *o;
3258    CLIENT_AUTH *a;
3259    FOLDER *pf;
3260    POLICY p;
3261    LINK *k;
3262    // 引数チェック
3263    if (f == NULL || h == NULL)
3264    {
3265        return;
3266    }
3267
3268    pf = CfgGetFolder(f, "Policy");
3269    if (pf == NULL)
3270    {
3271        return;
3272    }
3273
3274    SiLoadPolicyCfg(&p, pf);
3275
3276    online = CfgGetBool(f, "Online");
3277
3278    o = CiLoadClientOption(CfgGetFolder(f, "ClientOption"));
3279    a = CiLoadClientAuth(CfgGetFolder(f, "ClientAuth"));
3280    if (o == NULL || a == NULL)
3281    {
3282        Free(o);
3283        CiFreeClientAuth(a);
3284        return;
3285    }
3286
3287    k = NewLink(h->Cedar, h, o, a, &p);
3288    if (k != NULL)
3289    {
3290        BUF *b;
3291        k->CheckServerCert = CfgGetBool(f, "CheckServerCert");
3292        b = CfgGetBuf(f, "ServerCert");
3293        if (b != NULL)
3294        {
3295            k->ServerCert = BufToX(b, false);
3296            FreeBuf(b);
3297        }
3298
3299        if (online)
3300        {
3301            k->Offline = true;
3302            SetLinkOnline(k);
3303        }
3304        else
3305        {
3306            k->Offline = false;
3307            SetLinkOffline(k);
3308        }
3309        ReleaseLink(k);
3310    }
3311
3312    Free(o);
3313    CiFreeClientAuth(a);
3314}
3315
3316// 仮想 HUB の SecureNAT の書き込み
3317void SiWriteSecureNAT(HUB *h, FOLDER *f)
3318{
3319    // 引数チェック
3320    if (h == NULL || f == NULL)
3321    {
3322        return;
3323    }
3324
3325    CfgAddBool(f, "Disabled", h->EnableSecureNAT ? false : true);
3326
3327    NiWriteVhOptionEx(h->SecureNATOption, f);
3328}
3329
3330// 仮想 HUB の管理オプションの読み込み
3331void SiLoadHubAdminOptions(HUB *h, FOLDER *f)
3332{
3333    TOKEN_LIST *t;
3334    // 引数チェック
3335    if (h == NULL || f == NULL)
3336    {
3337        return;
3338    }
3339
3340    t = CfgEnumItemToTokenList(f);
3341    if (t != NULL)
3342    {
3343        UINT i;
3344
3345        LockList(h->AdminOptionList);
3346        {
3347            DeleteAllHubAdminOption(h, false);
3348
3349            for (i = 0;i < t->NumTokens;i++)
3350            {
3351                char *name = t->Token[i];
3352                ADMIN_OPTION *a;
3353                UINT value = CfgGetInt(f, name);;
3354
3355                Trim(name);
3356
3357                a = ZeroMalloc(sizeof(ADMIN_OPTION));
3358                StrCpy(a->Name, sizeof(a->Name), name);
3359                a->Value = value;
3360
3361                Insert(h->AdminOptionList, a);
3362            }
3363
3364            AddHubAdminOptionsDefaults(h, false);
3365        }
3366        UnlockList(h->AdminOptionList);
3367
3368        FreeToken(t);
3369    }
3370}
3371
3372// 仮想 HUB の管理オプションの書き込み
3373void SiWriteHubAdminOptions(FOLDER *f, HUB *h)
3374{
3375    // 引数チェック
3376    if (f == NULL || h == NULL)
3377    {
3378        return;
3379    }
3380
3381    LockList(h->AdminOptionList);
3382    {
3383        UINT i;
3384        for (i = 0;i < LIST_NUM(h->AdminOptionList);i++)
3385        {
3386            ADMIN_OPTION *a = LIST_DATA(h->AdminOptionList, i);
3387
3388            CfgAddInt(f, a->Name, a->Value);
3389        }
3390    }
3391    UnlockList(h->AdminOptionList);
3392}
3393
3394// 仮想 HUB のリンクリストの書き込み
3395void SiWriteHubLinks(FOLDER *f, HUB *h)
3396{
3397    // 引数チェック
3398    if (f == NULL || h == NULL)
3399    {
3400        return;
3401    }
3402
3403    LockList(h->LinkList);
3404    {
3405        UINT i;
3406        for (i = 0;i < LIST_NUM(h->LinkList);i++)
3407        {
3408            LINK *k = LIST_DATA(h->LinkList, i);
3409            char name[MAX_SIZE];
3410            Format(name, sizeof(name), "Cascade%u", i);
3411            SiWriteHubLinkCfg(CfgCreateFolder(f, name), k);
3412        }
3413    }
3414    UnlockList(h->LinkList);
3415}
3416
3417// リンクリストの読み込み
3418void SiLoadHubLinks(HUB *h, FOLDER *f)
3419{
3420    TOKEN_LIST *t;
3421    UINT i;
3422    // 引数チェック
3423    if (h == NULL || f == NULL)
3424    {
3425        return;
3426    }
3427
3428    t = CfgEnumFolderToTokenList(f);
3429
3430    for (i = 0;i < t->NumTokens;i++)
3431    {
3432        char *name = t->Token[i];
3433        SiLoadHubLinkCfg(CfgGetFolder(f, name), h);
3434    }
3435
3436    FreeToken(t);
3437}
3438
3439// アクセスリスト項目の書き込み
3440void SiWriteHubAccessCfg(FOLDER *f, ACCESS *a)
3441{
3442    // 引数チェック
3443    if (f == NULL || a == NULL)
3444    {
3445        return;
3446    }
3447
3448    CfgAddUniStr(f, "Note", a->Note);
3449    CfgAddBool(f, "Active", a->Active);
3450    CfgAddInt(f, "Priority", a->Priority);
3451    CfgAddBool(f, "Discard", a->Discard);
3452    CfgAddBool(f, "IsIPv6", a->IsIPv6);
3453
3454    if (a->IsIPv6 == false)
3455    {
3456        CfgAddIp32(f, "SrcIpAddress", a->SrcIpAddress);
3457        CfgAddIp32(f, "SrcSubnetMask", a->SrcSubnetMask);
3458        CfgAddIp32(f, "DestIpAddress", a->DestIpAddress);
3459        CfgAddIp32(f, "DestSubnetMask", a->DestSubnetMask);
3460    }
3461    else
3462    {
3463        CfgAddIp6Addr(f, "SrcIpAddress6", &a->SrcIpAddress6);
3464        CfgAddIp6Addr(f, "SrcSubnetMask6", &a->SrcSubnetMask6);
3465        CfgAddIp6Addr(f, "DestIpAddress6", &a->DestIpAddress6);
3466        CfgAddIp6Addr(f, "DestSubnetMask6", &a->DestSubnetMask6);
3467    }
3468
3469    CfgAddInt(f, "Protocol", a->Protocol);
3470    CfgAddInt(f, "SrcPortStart", a->SrcPortStart);
3471    CfgAddInt(f, "SrcPortEnd", a->SrcPortEnd);
3472    CfgAddInt(f, "DestPortStart", a->DestPortStart);
3473    CfgAddInt(f, "DestPortEnd", a->DestPortEnd);
3474    CfgAddStr(f, "SrcUsername", a->SrcUsername);
3475    CfgAddStr(f, "DestUsername", a->DestUsername);
3476    CfgAddBool(f, "CheckSrcMac", a->CheckSrcMac);
3477
3478    if (a->CheckSrcMac)
3479    {
3480        char tmp[MAX_PATH];
3481
3482        MacToStr(tmp, sizeof(tmp), a->SrcMacAddress);
3483        CfgAddStr(f, "SrcMacAddress", tmp);
3484
3485        MacToStr(tmp, sizeof(tmp), a->SrcMacMask);
3486        CfgAddStr(f, "SrcMacMask", tmp);
3487    }
3488
3489    CfgAddBool(f, "CheckDstMac", a->CheckDstMac);
3490
3491    if (a->CheckDstMac)
3492    {
3493        char tmp[MAX_PATH];
3494
3495        MacToStr(tmp, sizeof(tmp), a->DstMacAddress);
3496        CfgAddStr(f, "DstMacAddress", tmp);
3497
3498        MacToStr(tmp, sizeof(tmp), a->DstMacMask);
3499        CfgAddStr(f, "DstMacMask", tmp);
3500    }
3501
3502    CfgAddBool(f, "CheckTcpState", a->CheckTcpState);
3503    CfgAddBool(f, "Established", a->Established);
3504
3505    CfgAddInt(f, "Delay", a->Delay);
3506    CfgAddInt(f, "Jitter", a->Jitter);
3507    CfgAddInt(f, "Loss", a->Loss);
3508}
3509
3510// アクセスリスト項目の読み込み
3511void SiLoadHubAccessCfg(HUB *h, FOLDER *f)
3512{
3513    ACCESS a;
3514    char tmp[MAX_PATH];
3515    // 引数チェック
3516    if (h == NULL || f == NULL)
3517    {
3518        return;
3519    }
3520
3521    Zero(&a, sizeof(a));
3522
3523    CfgGetUniStr(f, "Note", a.Note, sizeof(a.Note));
3524    a.Active = CfgGetBool(f, "Active");
3525    a.Priority = CfgGetInt(f, "Priority");
3526    a.Discard = CfgGetBool(f, "Discard");
3527    a.IsIPv6 = CfgGetBool(f, "IsIPv6");
3528
3529    if (a.IsIPv6 == false)
3530    {
3531        a.SrcIpAddress = CfgGetIp32(f, "SrcIpAddress");
3532        a.SrcSubnetMask = CfgGetIp32(f, "SrcSubnetMask");
3533        a.DestIpAddress = CfgGetIp32(f, "DestIpAddress");
3534        a.DestSubnetMask = CfgGetIp32(f, "DestSubnetMask");
3535    }
3536    else
3537    {
3538        CfgGetIp6Addr(f, "SrcIpAddress6", &a.SrcIpAddress6);
3539        CfgGetIp6Addr(f, "SrcSubnetMask6", &a.SrcSubnetMask6);
3540        CfgGetIp6Addr(f, "DestIpAddress6", &a.DestIpAddress6);
3541        CfgGetIp6Addr(f, "DestSubnetMask6", &a.DestSubnetMask6);
3542    }
3543
3544    a.Protocol = CfgGetInt(f, "Protocol");
3545    a.SrcPortStart = CfgGetInt(f, "SrcPortStart");
3546    a.SrcPortEnd = CfgGetInt(f, "SrcPortEnd");
3547    a.DestPortStart = CfgGetInt(f, "DestPortStart");
3548    a.DestPortEnd = CfgGetInt(f, "DestPortEnd");
3549    CfgGetStr(f, "SrcUsername", a.SrcUsername, sizeof(a.SrcUsername));
3550    CfgGetStr(f, "DestUsername", a.DestUsername, sizeof(a.DestUsername));
3551    a.CheckSrcMac = CfgGetBool(f, "CheckSrcMac");
3552
3553    if (CfgGetByte(f, "SrcMacAddress", a.SrcMacAddress, sizeof(a.SrcMacAddress)) == 0)
3554    {
3555        CfgGetStr(f, "SrcMacAddress", tmp, sizeof(tmp));
3556        if (StrToMac(a.SrcMacAddress, tmp) == false)
3557        {
3558            a.CheckSrcMac = false;
3559        }
3560    }
3561
3562    if (CfgGetByte(f, "SrcMacMask", a.SrcMacMask, sizeof(a.SrcMacMask)) == 0)
3563    {
3564        CfgGetStr(f, "SrcMacMask", tmp, sizeof(tmp));
3565        if (StrToMac(a.SrcMacMask, tmp) == false)
3566        {
3567            a.CheckSrcMac = false;
3568        }
3569    }
3570
3571    a.CheckDstMac = CfgGetBool(f, "CheckDstMac");
3572
3573    if (CfgGetByte(f, "DstMacAddress", a.DstMacAddress, sizeof(a.DstMacAddress)) == 0)
3574    {
3575        CfgGetStr(f, "DstMacAddress", tmp, sizeof(tmp));
3576        if (StrToMac(a.DstMacAddress, tmp) == false)
3577        {
3578            a.CheckDstMac = false;
3579        }
3580    }
3581
3582    if (CfgGetByte(f, "DstMacMask", a.DstMacMask, sizeof(a.DstMacMask)) == 0)
3583    {
3584        CfgGetStr(f, "DstMacMask", tmp, sizeof(tmp));
3585        if (StrToMac(a.DstMacMask, tmp) == false)
3586        {
3587            a.CheckDstMac = false;
3588        }
3589    }
3590
3591    a.CheckTcpState = CfgGetBool(f, "CheckTcpState");
3592    a.Established = CfgGetBool(f, "Established");
3593    a.Delay = MAKESURE(CfgGetInt(f, "Delay"), 0, HUB_ACCESSLIST_DELAY_MAX);
3594    a.Jitter = MAKESURE(CfgGetInt(f, "Jitter"), 0, HUB_ACCESSLIST_JITTER_MAX);
3595    a.Loss = MAKESURE(CfgGetInt(f, "Loss"), 0, HUB_ACCESSLIST_LOSS_MAX);
3596
3597    AddAccessList(h, &a);
3598}
3599
3600// アクセスリストの書き込み
3601void SiWriteHubAccessLists(FOLDER *f, HUB *h)
3602{
3603    // 引数チェック
3604    if (f == NULL || h == NULL)
3605    {
3606        return;
3607    }
3608
3609    LockList(h->AccessList);
3610    {
3611        UINT i;
3612        for (i = 0;i < LIST_NUM(h->AccessList);i++)
3613        {
3614            ACCESS *a = LIST_DATA(h->AccessList, i);
3615            char name[MAX_SIZE];
3616            ToStr(name, a->Id);
3617            SiWriteHubAccessCfg(CfgCreateFolder(f, name), a);
3618        }
3619    }
3620    UnlockList(h->AccessList);
3621}
3622
3623// アクセスリストの読み込み
3624void SiLoadHubAccessLists(HUB *h, FOLDER *f)
3625{
3626    TOKEN_LIST *t;
3627    UINT i;
3628    // 引数チェック
3629    if (f == NULL || h == NULL)
3630    {
3631        return;
3632    }
3633
3634    t = CfgEnumFolderToTokenList(f);
3635
3636    for (i = 0;i < t->NumTokens;i++)
3637    {
3638        char *name = t->Token[i];
3639        UINT id = ToInt(name);
3640        SiLoadHubAccessCfg(h, CfgGetFolder(f, name));
3641    }
3642
3643    FreeToken(t);
3644}
3645
3646// HUB_OPTION の読み込み
3647void SiLoadHubOptionCfg(FOLDER *f, HUB_OPTION *o)
3648{
3649    char tmp[MAX_SIZE];
3650    // 引数チェック
3651    if (f == NULL || o == NULL)
3652    {
3653        return;
3654    }
3655
3656    o->MaxSession = CfgGetInt(f, "MaxSession");
3657    o->NoArpPolling = CfgGetBool(f, "NoArpPolling");
3658    o->NoIPv6AddrPolling = CfgGetBool(f, "NoIPv6AddrPolling");
3659    o->NoIpTable = CfgGetBool(f, "NoIpTable");
3660    o->NoEnum = CfgGetBool(f, "NoEnum");
3661    o->FilterPPPoE = CfgGetBool(f, "FilterPPPoE");
3662    o->FilterOSPF = CfgGetBool(f, "FilterOSPF");
3663    o->FilterIPv4 = CfgGetBool(f, "FilterIPv4");
3664    o->FilterIPv6 = CfgGetBool(f, "FilterIPv6");
3665    o->FilterNonIP = CfgGetBool(f, "FilterNonIP");
3666    o->FilterBPDU = CfgGetBool(f, "FilterBPDU");
3667    o->NoIPv4PacketLog = CfgGetBool(f, "NoIPv4PacketLog");
3668    o->NoIPv6PacketLog = CfgGetBool(f, "NoIPv6PacketLog");
3669    o->NoIPv6DefaultRouterInRAWhenIPv6 = CfgGetBool(f, "NoIPv6DefaultRouterInRAWhenIPv6");
3670    o->DisableIPParsing = CfgGetBool(f, "DisableIPParsing");
3671    o->YieldAfterStorePacket = CfgGetBool(f, "YieldAfterStorePacket");
3672    o->NoSpinLockForPacketDelay = CfgGetBool(f, "NoSpinLockForPacketDelay");
3673    o->BroadcastStormDetectionThreshold = CfgGetInt(f, "BroadcastStormDetectionThreshold");
3674    o->ClientMinimumRequiredBuild = CfgGetInt(f, "ClientMinimumRequiredBuild");
3675    o->RequiredClientId = CfgGetInt(f, "RequiredClientId");
3676    o->NoManageVlanId = CfgGetBool(f, "NoManageVlanId");
3677    o->VlanTypeId = 0;
3678    if (CfgGetStr(f, "VlanTypeId", tmp, sizeof(tmp)))
3679    {
3680        o->VlanTypeId = HexToInt(tmp);
3681    }
3682    if (o->VlanTypeId == 0)
3683    {
3684        o->VlanTypeId = MAC_PROTO_TAGVLAN;
3685    }
3686    o->FixForDLinkBPDU = CfgGetBool(f, "FixForDLinkBPDU");
3687    o->NoLookBPDUBridgeId = CfgGetBool(f, "NoLookBPDUBridgeId");
3688
3689    // デフォルトで有効
3690    if (CfgIsItem(f, "ManageOnlyPrivateIP"))
3691    {
3692        o->ManageOnlyPrivateIP = CfgGetBool(f, "ManageOnlyPrivateIP");
3693    }
3694    else
3695    {
3696        o->ManageOnlyPrivateIP = true;
3697    }
3698    if (CfgIsItem(f, "ManageOnlyLocalUnicastIPv6"))
3699    {
3700        o->ManageOnlyLocalUnicastIPv6 = CfgGetBool(f, "ManageOnlyLocalUnicastIPv6");
3701    }
3702    else
3703    {
3704        o->ManageOnlyLocalUnicastIPv6 = true;
3705    }
3706    if (CfgIsItem(f, "NoMacAddressLog"))
3707    {
3708        o->NoMacAddressLog = CfgGetBool(f, "NoMacAddressLog");
3709    }
3710    else
3711    {
3712        o->NoMacAddressLog = true;
3713    }
3714}
3715
3716// HUB_OPTION の書き込み
3717void SiWriteHubOptionCfg(FOLDER *f, HUB_OPTION *o)
3718{
3719    char tmp[MAX_SIZE];
3720    // 引数チェック
3721    if (f == NULL || o == NULL)
3722    {
3723        return;
3724    }
3725
3726    CfgAddInt(f, "MaxSession", o->MaxSession);
3727    CfgAddBool(f, "NoArpPolling", o->NoArpPolling);
3728    CfgAddBool(f, "NoIPv6AddrPolling", o->NoIPv6AddrPolling);
3729    CfgAddBool(f, "NoIpTable", o->NoIpTable);
3730    CfgAddBool(f, "NoEnum", o->NoEnum);
3731    CfgAddBool(f, "FilterPPPoE", o->FilterPPPoE);
3732    CfgAddBool(f, "FilterOSPF", o->FilterOSPF);
3733    CfgAddBool(f, "FilterIPv4", o->FilterIPv4);
3734    CfgAddBool(f, "FilterIPv6", o->FilterIPv6);
3735    CfgAddBool(f, "FilterNonIP", o->FilterNonIP);
3736    CfgAddBool(f, "NoIPv4PacketLog", o->NoIPv4PacketLog);
3737    CfgAddBool(f, "NoIPv6PacketLog", o->NoIPv6PacketLog);
3738    CfgAddBool(f, "FilterBPDU", o->FilterBPDU);
3739    CfgAddBool(f, "NoIPv6DefaultRouterInRAWhenIPv6", o->NoIPv6DefaultRouterInRAWhenIPv6);
3740    CfgAddBool(f, "NoMacAddressLog", o->NoMacAddressLog);
3741    CfgAddBool(f, "ManageOnlyPrivateIP", o->ManageOnlyPrivateIP);
3742    CfgAddBool(f, "ManageOnlyLocalUnicastIPv6", o->ManageOnlyLocalUnicastIPv6);
3743    CfgAddBool(f, "DisableIPParsing", o->DisableIPParsing);
3744    CfgAddBool(f, "YieldAfterStorePacket", o->YieldAfterStorePacket);
3745    CfgAddBool(f, "NoSpinLockForPacketDelay", o->NoSpinLockForPacketDelay);
3746    CfgAddInt(f, "BroadcastStormDetectionThreshold", o->BroadcastStormDetectionThreshold);
3747    CfgAddInt(f, "ClientMinimumRequiredBuild", o->ClientMinimumRequiredBuild);
3748    CfgAddInt(f, "RequiredClientId", o->RequiredClientId);
3749    CfgAddBool(f, "NoManageVlanId", o->NoManageVlanId);
3750    Format(tmp, sizeof(tmp), "0x%x", o->VlanTypeId);
3751    CfgAddStr(f, "VlanTypeId", tmp);
3752    if (o->FixForDLinkBPDU)
3753    {
3754        CfgAddBool(f, "FixForDLinkBPDU", o->FixForDLinkBPDU);
3755    }
3756    CfgAddBool(f, "NoLookBPDUBridgeId", o->NoLookBPDUBridgeId);
3757}
3758
3759// ユーザーの書き込み
3760void SiWriteUserCfg(FOLDER *f, USER *u)
3761{
3762    AUTHPASSWORD *password;
3763    // 引数チェック
3764    if (f == NULL || u == NULL)
3765    {
3766        return;
3767    }
3768
3769    Lock(u->lock);
3770    {
3771        CfgAddUniStr(f, "RealName", u->RealName);
3772        CfgAddUniStr(f, "Note", u->Note);
3773        if (u->Group != NULL)
3774        {
3775            CfgAddStr(f, "GroupName", u->GroupName);
3776        }
3777        CfgAddInt64(f, "CreatedTime", u->CreatedTime);
3778        CfgAddInt64(f, "UpdatedTime", u->UpdatedTime);
3779        CfgAddInt64(f, "ExpireTime", u->ExpireTime);
3780        CfgAddInt64(f, "LastLoginTime", u->LastLoginTime);
3781        CfgAddInt(f, "NumLogin", u->NumLogin);
3782        if (u->Policy != NULL)
3783        {
3784            SiWritePolicyCfg(CfgCreateFolder(f, "Policy"), u->Policy, false);
3785        }
3786        SiWriteTraffic(f, "Traffic", u->Traffic);
3787
3788        CfgAddInt(f, "AuthType", u->AuthType);
3789        if (u->AuthData != NULL)
3790        {
3791            switch (u->AuthType)
3792            {
3793            case AUTHTYPE_ANONYMOUS:
3794                break;
3795
3796            case AUTHTYPE_PASSWORD:
3797                password = (AUTHPASSWORD *)u->AuthData;
3798                CfgAddByte(f, "AuthPassword", password->HashedKey, sizeof(password->HashedKey));
3799                break;
3800            }
3801        }
3802    }
3803    Unlock(u->lock);
3804}
3805
3806// ユーザーの読み込み
3807void SiLoadUserCfg(HUB *h, FOLDER *f)
3808{
3809    char *username;
3810    wchar_t realname[MAX_SIZE];
3811    wchar_t note[MAX_SIZE];
3812    char groupname[MAX_SIZE];
3813    FOLDER *pf;
3814    UINT64 created_time;
3815    UINT64 updated_time;
3816    UINT64 expire_time;
3817    UINT64 last_login_time;
3818    UINT num_login;
3819    POLICY p;
3820    TRAFFIC t;
3821    UINT authtype;
3822    void *authdata;
3823    X_SERIAL *serial = NULL;
3824    UCHAR hashed_password[SHA1_SIZE];
3825    USER *u;
3826    USERGROUP *g;
3827    // 引数チェック
3828    if (h == NULL || f == NULL)
3829    {
3830        return;
3831    }
3832
3833    username = f->Name;
3834    CfgGetUniStr(f, "RealName", realname, sizeof(realname));
3835    CfgGetUniStr(f, "Note", note, sizeof(note));
3836    CfgGetStr(f, "GroupName", groupname, sizeof(groupname));
3837
3838    created_time = CfgGetInt64(f, "CreatedTime");
3839    updated_time = CfgGetInt64(f, "UpdatedTime");
3840    expire_time = CfgGetInt64(f, "ExpireTime");
3841    last_login_time = CfgGetInt64(f, "LastLoginTime");
3842    num_login = CfgGetInt(f, "NumLogin");
3843    pf = CfgGetFolder(f, "Policy");
3844    if (pf != NULL)
3845    {
3846        SiLoadPolicyCfg(&p, pf);
3847    }
3848    SiLoadTraffic(f, "Traffic", &t);
3849
3850    authtype = CfgGetInt(f, "AuthType");
3851    authdata = NULL;
3852
3853    switch (authtype)
3854    {
3855    case AUTHTYPE_PASSWORD:
3856        // 通常のパスワード認証
3857        CfgGetByte(f, "AuthPassword", hashed_password, sizeof(hashed_password));
3858        authdata = NewPasswordAuthDataRaw(hashed_password);
3859        break;
3860
3861    default:
3862        // それ以外の認証方法が指定された
3863        authtype = AUTHTYPE_ANONYMOUS;
3864        authdata = NULL;
3865        break;
3866    }
3867
3868    // ユーザーの追加
3869    AcLock(h);
3870    {
3871        if (StrLen(groupname) > 0)
3872        {
3873            g = AcGetGroup(h, groupname);
3874        }
3875        else
3876        {
3877            g = NULL;
3878        }
3879
3880        u = NewUser(username, realname, note, authtype, authdata);
3881        if (u != NULL)
3882        {
3883            if (g != NULL)
3884            {
3885                JoinUserToGroup(u, g);
3886            }
3887
3888            SetUserTraffic(u, &t);
3889
3890            if (pf != NULL)
3891            {
3892                SetUserPolicy(u, &p);
3893            }
3894
3895            Lock(u->lock);
3896            {
3897                u->CreatedTime = created_time;
3898                u->UpdatedTime = updated_time;
3899                u->ExpireTime = expire_time;
3900                u->LastLoginTime = last_login_time;
3901                u->NumLogin = num_login;
3902            }
3903            Unlock(u->lock);
3904
3905            AcAddUser(h, u);
3906
3907            ReleaseUser(u);
3908        }
3909
3910        if (g != NULL)
3911        {
3912            ReleaseGroup(g);
3913        }
3914    }
3915    AcUnlock(h);
3916
3917    if (serial != NULL)
3918    {
3919        FreeXSerial(serial);
3920    }
3921}
3922
3923// ユーザーリストの書き込み
3924void SiWriteUserList(FOLDER *f, LIST *o)
3925{
3926    // 引数チェック
3927    if (f == NULL || o == NULL)
3928    {
3929        return;
3930    }
3931
3932    LockList(o);
3933    {
3934        UINT i;
3935        for (i = 0;i < LIST_NUM(o);i++)
3936        {
3937            USER *u = LIST_DATA(o, i);
3938            SiWriteUserCfg(CfgCreateFolder(f, u->Name), u);
3939        }
3940    }
3941    UnlockList(o);
3942}
3943
3944// ユーザーリストの読み込み
3945void SiLoadUserList(HUB *h, FOLDER *f)
3946{
3947    TOKEN_LIST *t;
3948    UINT i;
3949    char *name;
3950    // 引数チェック
3951    if (f == NULL || h == NULL)
3952    {
3953        return;
3954    }
3955
3956    t = CfgEnumFolderToTokenList(f);
3957
3958    for (i = 0;i < t->NumTokens;i++)
3959    {
3960        FOLDER *ff;
3961        name = t->Token[i];
3962        ff = CfgGetFolder(f, name);
3963        SiLoadUserCfg(h, ff);
3964    }
3965
3966    FreeToken(t);
3967}
3968
3969// グループ情報の書き込み
3970void SiWriteGroupCfg(FOLDER *f, USERGROUP *g)
3971{
3972    // 引数チェック
3973    if (f == NULL || g == NULL)
3974    {
3975        return;
3976    }
3977
3978    Lock(g->lock);
3979    {
3980        CfgAddUniStr(f, "RealName", g->RealName);
3981        CfgAddUniStr(f, "Note", g->Note);
3982        if (g->Policy != NULL)
3983        {
3984            SiWritePolicyCfg(CfgCreateFolder(f, "Policy"), g->Policy, false);
3985        }
3986        SiWriteTraffic(f, "Traffic", g->Traffic);
3987    }
3988    Unlock(g->lock);
3989}
3990
3991// グループ情報の読み込み
3992void SiLoadGroupCfg(HUB *h, FOLDER *f)
3993{
3994    wchar_t realname[MAX_SIZE];
3995    wchar_t note[MAX_SIZE];
3996    char *name;
3997    FOLDER *pf;
3998    POLICY p;
3999    TRAFFIC t;
4000    USERGROUP *g;
4001    // 引数チェック
4002    if (h == NULL || f == NULL)
4003    {
4004        return;
4005    }
4006
4007    name = f->Name;
4008
4009    CfgGetUniStr(f, "RealName", realname, sizeof(realname));
4010    CfgGetUniStr(f, "Note", note, sizeof(note));
4011
4012    pf = CfgGetFolder(f, "Policy");
4013    if (pf != NULL)
4014    {
4015        SiLoadPolicyCfg(&p, pf);
4016    }
4017
4018    SiLoadTraffic(f, "Traffic", &t);
4019
4020    g = NewGroup(name, realname, note);
4021    if (g == NULL)
4022    {
4023        return;
4024    }
4025
4026    if (pf != NULL)
4027    {
4028        SetGroupPolicy(g, &p);
4029    }
4030
4031    SetGroupTraffic(g, &t);
4032
4033    AcLock(h);
4034    {
4035        AcAddGroup(h, g);
4036    }
4037    AcUnlock(h);
4038
4039    ReleaseGroup(g);
4040}
4041
4042// グループリストの書き込み
4043void SiWriteGroupList(FOLDER *f, LIST *o)
4044{
4045    // 引数チェック
4046    if (f == NULL || o == NULL)
4047    {
4048        return;
4049    }
4050
4051    LockList(o);
4052    {
4053        UINT i;
4054        for (i = 0;i < LIST_NUM(o);i++)
4055        {
4056            USERGROUP *g = LIST_DATA(o, i);
4057            SiWriteGroupCfg(CfgCreateFolder(f, g->Name), g);
4058        }
4059    }
4060    UnlockList(o);
4061}
4062
4063// グループリストの読み込み
4064void SiLoadGroupList(HUB *h, FOLDER *f)
4065{
4066    TOKEN_LIST *t;
4067    UINT i;
4068    char *name;
4069    // 引数チェック
4070    if (f == NULL || h == NULL)
4071    {
4072        return;
4073    }
4074
4075    t = CfgEnumFolderToTokenList(f);
4076
4077    for (i = 0;i < t->NumTokens;i++)
4078    {
4079        name = t->Token[i];
4080        SiLoadGroupCfg(h, CfgGetFolder(f, name));
4081    }
4082
4083    FreeToken(t);
4084}
4085
4086// 無効な証明書リストの書き込み
4087void SiWriteCrlList(FOLDER *f, LIST *o)
4088{
4089    // 引数チェック
4090    if (f == NULL || o == NULL)
4091    {
4092        return;
4093    }
4094
4095    LockList(o);
4096    {
4097        UINT i;
4098        for (i = 0;i < LIST_NUM(o);i++)
4099        {
4100            char name[MAX_SIZE];
4101            CRL *crl = LIST_DATA(o, i);
4102            FOLDER *ff;
4103            NAME *n;
4104
4105            Format(name, sizeof(name), "Crl%u", i);
4106
4107            ff = CfgCreateFolder(f, name);
4108            n = crl->Name;
4109
4110            if (UniIsEmptyStr(n->CommonName) == false)
4111            {
4112                CfgAddUniStr(ff, "CommonName", n->CommonName);
4113            }
4114
4115            if (UniIsEmptyStr(n->Organization) == false)
4116            {
4117                CfgAddUniStr(ff, "Organization", n->Organization);
4118            }
4119
4120            if (UniIsEmptyStr(n->Unit) == false)
4121            {
4122                CfgAddUniStr(ff, "Unit", n->Unit);
4123            }
4124
4125            if (UniIsEmptyStr(n->Country) == false)
4126            {
4127                CfgAddUniStr(ff, "Country", n->Country);
4128            }
4129
4130            if (UniIsEmptyStr(n->State) == false)
4131            {
4132                CfgAddUniStr(ff, "State", n->State);
4133            }
4134
4135            if (UniIsEmptyStr(n->Local) == false)
4136            {
4137                CfgAddUniStr(ff, "Local", n->Local);
4138            }
4139
4140            if (IsZero(crl->DigestMD5, MD5_SIZE) == false)
4141            {
4142                char tmp[MAX_SIZE];
4143
4144                BinToStr(tmp, sizeof(tmp), crl->DigestMD5, MD5_SIZE);
4145                CfgAddStr(ff, "DigestMD5", tmp);
4146            }
4147
4148            if (IsZero(crl->DigestSHA1, SHA1_SIZE) == false)
4149            {
4150                char tmp[MAX_SIZE];
4151
4152                BinToStr(tmp, sizeof(tmp), crl->DigestSHA1, SHA1_SIZE);
4153                CfgAddStr(ff, "DigestSHA1", tmp);
4154            }
4155
4156            if (crl->Serial != NULL)
4157            {
4158                char tmp[MAX_SIZE];
4159
4160                BinToStr(tmp, sizeof(tmp), crl->Serial->data, crl->Serial->size);
4161                CfgAddStr(ff, "Serial", tmp);
4162            }
4163        }
4164    }
4165    UnlockList(o);
4166}
4167
4168// 無効な証明書リストの読み込み
4169void SiLoadCrlList(LIST *o, FOLDER *f)
4170{
4171    // 引数チェック
4172    if (o == NULL || f == NULL)
4173    {
4174        return;
4175    }
4176
4177    LockList(o);
4178    {
4179        UINT i;
4180        TOKEN_LIST *t;
4181
4182        t = CfgEnumFolderToTokenList(f);
4183
4184        for (i = 0;i < t->NumTokens;i++)
4185        {
4186            CRL *crl;
4187            FOLDER *ff = CfgGetFolder(f, t->Token[i]);
4188            wchar_t cn[MAX_SIZE], org[MAX_SIZE], u[MAX_SIZE], c[MAX_SIZE],
4189                st[MAX_SIZE], l[MAX_SIZE];
4190            char tmp[MAX_SIZE];
4191
4192            if (ff != NULL)
4193            {
4194                BUF *b;
4195
4196                crl = ZeroMalloc(sizeof(CRL));
4197
4198                CfgGetUniStr(ff, "CommonName", cn, sizeof(cn));
4199                CfgGetUniStr(ff, "Organization", org, sizeof(org));
4200                CfgGetUniStr(ff, "Unit", u, sizeof(u));
4201                CfgGetUniStr(ff, "Country", c, sizeof(c));
4202                CfgGetUniStr(ff, "State", st, sizeof(st));
4203                CfgGetUniStr(ff, "Local", l, sizeof(l));
4204
4205                crl->Name = NewName(cn, org, u, c, st, l);
4206
4207                if (CfgGetStr(ff, "Serial", tmp, sizeof(tmp)))
4208                {
4209                    b = StrToBin(tmp);
4210
4211                    if (b != NULL)
4212                    {
4213                        if (b->Size >= 1)
4214                        {
4215                            crl->Serial = NewXSerial(b->Buf, b->Size);
4216                        }
4217
4218                        FreeBuf(b);
4219                    }
4220                }
4221
4222                if (CfgGetStr(ff, "DigestMD5", tmp, sizeof(tmp)))
4223                {
4224                    b = StrToBin(tmp);
4225
4226                    if (b != NULL)
4227                    {
4228                        if (b->Size == MD5_SIZE)
4229                        {
4230                            Copy(crl->DigestMD5, b->Buf, MD5_SIZE);
4231                        }
4232
4233                        FreeBuf(b);
4234                    }
4235                }
4236
4237                if (CfgGetStr(ff, "DigestSHA1", tmp, sizeof(tmp)))
4238                {
4239                    b = StrToBin(tmp);
4240
4241                    if (b != NULL)
4242                    {
4243                        if (b->Size == SHA1_SIZE)
4244                        {
4245                            Copy(crl->DigestSHA1, b->Buf, SHA1_SIZE);
4246                        }
4247
4248                        FreeBuf(b);
4249                    }
4250                }
4251
4252                Insert(o, crl);
4253            }
4254        }
4255
4256        FreeToken(t);
4257    }
4258    UnlockList(o);
4259}
4260
4261// 証明書リストの書き込み
4262void SiWriteCertList(FOLDER *f, LIST *o)
4263{
4264    // 引数チェック
4265    if (f == NULL || o == NULL)
4266    {
4267        return;
4268    }
4269
4270    LockList(o);
4271    {
4272        UINT i;
4273        X *x;
4274        for (i = 0;i < LIST_NUM(o);i++)
4275        {
4276            char name[MAX_SIZE];
4277            BUF *b;
4278            x = LIST_DATA(o, i);
4279            Format(name, sizeof(name), "Cert%u", i);
4280            b = XToBuf(x, false);
4281            if (b != NULL)
4282            {
4283                CfgAddBuf(CfgCreateFolder(f, name), "X509", b);
4284                FreeBuf(b);
4285            }
4286        }
4287    }
4288    UnlockList(o);
4289}
4290
4291// 証明書リストの読み込み
4292void SiLoadCertList(LIST *o, FOLDER *f)
4293{
4294    // 引数チェック
4295    if (o == NULL || f == NULL)
4296    {
4297        return;
4298    }
4299
4300    LockList(o);
4301    {
4302        UINT i;
4303        TOKEN_LIST *t;
4304
4305        t = CfgEnumFolderToTokenList(f);
4306
4307        for (i = 0;i < t->NumTokens;i++)
4308        {
4309            FOLDER *ff = CfgGetFolder(f, t->Token[i]);
4310            BUF *b;
4311
4312            b = CfgGetBuf(ff, "X509");
4313            if (b != NULL)
4314            {
4315                X *x = BufToX(b, false);
4316                if (x != NULL)
4317                {
4318                    Insert(o, x);
4319                }
4320                FreeBuf(b);
4321            }
4322        }
4323
4324        FreeToken(t);
4325    }
4326    UnlockList(o);
4327}
4328
4329// データベースの書き込み
4330void SiWriteHubDb(FOLDER *f, HUBDB *db)
4331{
4332    // 引数チェック
4333    if (f == NULL || db == NULL)
4334    {
4335        return;
4336    }
4337
4338    SiWriteUserList(CfgCreateFolder(f, "UserList"), db->UserList);
4339    SiWriteGroupList(CfgCreateFolder(f, "GroupList"), db->GroupList);
4340    SiWriteCertList(CfgCreateFolder(f, "CertList"), db->RootCertList);
4341    SiWriteCrlList(CfgCreateFolder(f, "CrlList"), db->CrlList);
4342}
4343
4344// データベースの読み込み
4345void SiLoadHubDb(HUB *h, FOLDER *f)
4346{
4347    // 引数チェック
4348    if (f == NULL || h == NULL)
4349    {
4350        return;
4351    }
4352
4353    SiLoadGroupList(h, CfgGetFolder(f, "GroupList"));
4354    SiLoadUserList(h, CfgGetFolder(f, "UserList"));
4355
4356    if (h->HubDb != NULL)
4357    {
4358        SiLoadCertList(h->HubDb->RootCertList, CfgGetFolder(f, "CertList"));
4359        SiLoadCrlList(h->HubDb->CrlList, CfgGetFolder(f, "CrlList"));
4360    }
4361}
4362
4363// 仮想 HUB 設定の書き込み
4364void SiWriteHubCfg(FOLDER *f, HUB *h)
4365{
4366    // 引数チェック
4367    if (f == NULL || h == NULL)
4368    {
4369        return;
4370    }
4371
4372    // パスワード
4373    CfgAddByte(f, "HashedPassword", h->HashedPassword, sizeof(h->HashedPassword));
4374    CfgAddByte(f, "SecurePassword", h->SecurePassword, sizeof(h->SecurePassword));
4375
4376    // Online / Offline フラグ
4377    if (h->Cedar->Bridge == false)
4378    {
4379        CfgAddBool(f, "Online", (h->Offline && (h->HubIsOnlineButHalting == false)) ? false : true);
4380    }
4381
4382    // トラフィック情報
4383    SiWriteTraffic(f, "Traffic", h->Traffic);
4384
4385    // HUB オプション
4386    SiWriteHubOptionCfg(CfgCreateFolder(f, "Option"), h->Option);
4387
4388    // メッセージ
4389    {
4390        FOLDER *folder = CfgCreateFolder(f, "Message");
4391
4392        if (IsEmptyUniStr(h->Msg) == false)
4393        {
4394            CfgAddUniStr(folder, "MessageText", h->Msg);
4395        }
4396    }
4397
4398    // HUB_LOG
4399    SiWriteHubLogCfg(CfgCreateFolder(f, "LogSetting"), &h->LogSetting);
4400
4401    if (h->Type == HUB_TYPE_STANDALONE)
4402    {
4403        // リンクリスト
4404        SiWriteHubLinks(CfgCreateFolder(f, "CascadeList"), h);
4405    }
4406
4407    if (h->Type != HUB_TYPE_FARM_STATIC)
4408    {
4409        if (GetServerCapsBool(h->Cedar->Server, "b_support_securenat"))
4410        {
4411            // SecureNAT
4412            SiWriteSecureNAT(h, CfgCreateFolder(f, "SecureNAT"));
4413        }
4414    }
4415
4416    // アクセスリスト
4417    SiWriteHubAccessLists(CfgCreateFolder(f, "AccessList"), h);
4418
4419    // 管理オプション
4420    SiWriteHubAdminOptions(CfgCreateFolder(f, "AdminOption"), h);
4421
4422    // HUB の種類
4423    CfgAddInt(f, "Type", h->Type);
4424
4425    // データベース
4426    if (h->Cedar->Bridge == false)
4427    {
4428        SiWriteHubDb(CfgCreateFolder(f, "SecurityAccountDatabase"), h->HubDb);
4429    }
4430
4431    // 利用状況
4432    CfgAddInt64(f, "LastCommTime", h->LastCommTime);
4433    CfgAddInt64(f, "LastLoginTime", h->LastLoginTime);
4434    CfgAddInt64(f, "CreatedTime", h->CreatedTime);
4435    CfgAddInt(f, "NumLogin", h->NumLogin);
4436}
4437
4438// ログオプションの読み込み
4439void SiLoadHubLogCfg(HUB_LOG *g, FOLDER *f)
4440{
4441    // 引数チェック
4442    if (f == NULL || g == NULL)
4443    {
4444        return;
4445    }
4446
4447    Zero(g, sizeof(HUB_LOG));
4448    g->SaveSecurityLog = CfgGetBool(f, "SaveSecurityLog");
4449    g->SecurityLogSwitchType = CfgGetInt(f, "SecurityLogSwitchType");
4450    g->SavePacketLog = CfgGetBool(f, "SavePacketLog");
4451    g->PacketLogSwitchType = CfgGetInt(f, "PacketLogSwitchType");
4452
4453    g->PacketLogConfig[PACKET_LOG_TCP_CONN] = CfgGetInt(f, "PACKET_LOG_TCP_CONN");
4454    g->PacketLogConfig[PACKET_LOG_TCP] = CfgGetInt(f, "PACKET_LOG_TCP");
4455    g->PacketLogConfig[PACKET_LOG_DHCP] = CfgGetInt(f, "PACKET_LOG_DHCP");
4456    g->PacketLogConfig[PACKET_LOG_UDP] = CfgGetInt(f, "PACKET_LOG_UDP");
4457    g->PacketLogConfig[PACKET_LOG_ICMP] = CfgGetInt(f, "PACKET_LOG_ICMP");
4458    g->PacketLogConfig[PACKET_LOG_IP] = CfgGetInt(f, "PACKET_LOG_IP");
4459    g->PacketLogConfig[PACKET_LOG_ARP] = CfgGetInt(f, "PACKET_LOG_ARP");
4460    g->PacketLogConfig[PACKET_LOG_ETHERNET] = CfgGetInt(f, "PACKET_LOG_ETHERNET");
4461}
4462
4463// ログオプションの書き込み
4464void SiWriteHubLogCfg(FOLDER *f, HUB_LOG *g)
4465{
4466    SiWriteHubLogCfgEx(f, g, false);
4467}
4468void SiWriteHubLogCfgEx(FOLDER *f, HUB_LOG *g, bool el_mode)
4469{
4470    // 引数チェック
4471    if (f == NULL || g == NULL)
4472    {
4473        return;
4474    }
4475
4476    if (el_mode == false)
4477    {
4478        CfgAddBool(f, "SaveSecurityLog", g->SaveSecurityLog);
4479        CfgAddInt(f, "SecurityLogSwitchType", g->SecurityLogSwitchType);
4480        CfgAddBool(f, "SavePacketLog", g->SavePacketLog);
4481    }
4482
4483    CfgAddInt(f, "PacketLogSwitchType", g->PacketLogSwitchType);
4484
4485    CfgAddInt(f, "PACKET_LOG_TCP_CONN", g->PacketLogConfig[PACKET_LOG_TCP_CONN]);
4486    CfgAddInt(f, "PACKET_LOG_TCP", g->PacketLogConfig[PACKET_LOG_TCP]);
4487    CfgAddInt(f, "PACKET_LOG_DHCP", g->PacketLogConfig[PACKET_LOG_DHCP]);
4488    CfgAddInt(f, "PACKET_LOG_UDP", g->PacketLogConfig[PACKET_LOG_UDP]);
4489    CfgAddInt(f, "PACKET_LOG_ICMP", g->PacketLogConfig[PACKET_LOG_ICMP]);
4490    CfgAddInt(f, "PACKET_LOG_IP", g->PacketLogConfig[PACKET_LOG_IP]);
4491    CfgAddInt(f, "PACKET_LOG_ARP", g->PacketLogConfig[PACKET_LOG_ARP]);
4492    CfgAddInt(f, "PACKET_LOG_ETHERNET", g->PacketLogConfig[PACKET_LOG_ETHERNET]);
4493}
4494
4495// 仮想 HUB 設定の読み込み
4496void SiLoadHubCfg(SERVER *s, FOLDER *f, char *name)
4497{
4498    HUB *h;
4499    CEDAR *c;
4500    HUB_OPTION o;
4501    bool online;
4502    UINT hub_old_type = 0;
4503    // 引数チェック
4504    if (s == NULL || f == NULL || name == NULL)
4505    {
4506        return;
4507    }
4508
4509    c = s->Cedar;
4510
4511    // オプションの取得
4512    Zero(&o, sizeof(o));
4513    SiLoadHubOptionCfg(CfgGetFolder(f, "Option"), &o);
4514
4515    // HUB の作成
4516    h = NewHub(c, name, &o);
4517    if (h != NULL)
4518    {
4519        HUB_LOG g;
4520
4521        // パスワード
4522        if (CfgGetByte(f, "HashedPassword", h->HashedPassword, sizeof(h->HashedPassword)) != sizeof(h->HashedPassword))
4523        {
4524            Hash(h->HashedPassword, "", 0, true);
4525        }
4526        if (CfgGetByte(f, "SecurePassword", h->SecurePassword, sizeof(h->SecurePassword)) != sizeof(h->SecurePassword))
4527        {
4528            HashPassword(h->SecurePassword, ADMINISTRATOR_USERNAME, "");
4529        }
4530
4531        // ログ設定
4532        Zero(&g, sizeof(g));
4533        SiLoadHubLogCfg(&g, CfgGetFolder(f, "LogSetting"));
4534        SetHubLogSetting(h, &g);
4535
4536        // Online / Offline フラグ
4537        if (h->Cedar->Bridge == false)
4538        {
4539            online = CfgGetBool(f, "Online");
4540        }
4541        else
4542        {
4543            online = true;
4544        }
4545
4546        // トラフィック情報
4547        SiLoadTraffic(f, "Traffic", h->Traffic);
4548
4549        // アクセスリスト
4550        SiLoadHubAccessLists(h, CfgGetFolder(f, "AccessList"));
4551
4552        // HUB の種類
4553        hub_old_type = h->Type = CfgGetInt(f, "Type");
4554        if (s->ServerType == SERVER_TYPE_STANDALONE)
4555        {
4556            if (h->Type != HUB_TYPE_STANDALONE)
4557            {
4558                // サーバーがスタンドアロンの場合は HUB の種類をスタンドアロンに変換する
4559                h->Type = HUB_TYPE_STANDALONE;
4560            }
4561        }
4562        else
4563        {
4564            if (h->Type == HUB_TYPE_STANDALONE)
4565            {
4566                // サーバーがファームコントローラの場合は HUB の種類をファーム対応にする
4567                h->Type = HUB_TYPE_FARM_DYNAMIC;
4568            }
4569        }
4570
4571        // メッセージ
4572        {
4573            FOLDER *folder = CfgGetFolder(f, "Message");
4574            if (folder != NULL)
4575            {
4576                wchar_t *tmp = Malloc(sizeof(wchar_t) * (HUB_MAXMSG_LEN + 1));
4577                if (CfgGetUniStr(folder, "MessageText", tmp, sizeof(wchar_t) * (HUB_MAXMSG_LEN + 1)))
4578                {
4579                    SetHubMsg(h, tmp);
4580                }
4581                Free(tmp);
4582            }
4583        }
4584
4585        // リンクリスト
4586        if (h->Type == HUB_TYPE_STANDALONE)
4587        {
4588            // リンクリストはスタンドアロン HUB の場合しか使用しない
4589            SiLoadHubLinks(h, CfgGetFolder(f, "CascadeList"));
4590        }
4591
4592        // SecureNAT
4593        if (GetServerCapsBool(h->Cedar->Server, "b_support_securenat"))
4594        {
4595            if (h->Type == HUB_TYPE_STANDALONE || h->Type == HUB_TYPE_FARM_DYNAMIC)
4596            {
4597                // SecureNAT はスタンドアロン HUB かダイナミック HUB の場合しか使用しない
4598                SiLoadSecureNAT(h, CfgGetFolder(f, "SecureNAT"));
4599
4600                if (h->Type != HUB_TYPE_STANDALONE && h->Cedar != NULL && h->Cedar->Server != NULL &&
4601                    h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
4602                {
4603                    NiClearUnsupportedVhOptionForDynamicHub(h->SecureNATOption,
4604                        hub_old_type == HUB_TYPE_STANDALONE);
4605                }
4606
4607            }
4608        }
4609
4610        // 管理オプション
4611        SiLoadHubAdminOptions(h, CfgGetFolder(f, "AdminOption"));
4612
4613        // データベース
4614        if (h->Cedar->Bridge == false)
4615        {
4616            SiLoadHubDb(h, CfgGetFolder(f, "SecurityAccountDatabase"));
4617        }
4618
4619        // 利用状況
4620        h->LastCommTime = CfgGetInt64(f, "LastCommTime");
4621        if (h->LastCommTime == 0)
4622        {
4623            h->LastCommTime = SystemTime64();
4624        }
4625        h->LastLoginTime = CfgGetInt64(f, "LastLoginTime");
4626        if (h->LastLoginTime == 0)
4627        {
4628            h->LastLoginTime = SystemTime64();
4629        }
4630        h->CreatedTime = CfgGetInt64(f, "CreatedTime");
4631        h->NumLogin = CfgGetInt(f, "NumLogin");
4632
4633        // HUB の動作開始
4634        AddHub(c, h);
4635
4636        if (online)
4637        {
4638            h->Offline = true;
4639            SetHubOnline(h);
4640        }
4641        else
4642        {
4643            h->Offline = false;
4644            SetHubOffline(h);
4645        }
4646
4647        WaitLogFlush(h->SecurityLogger);
4648        WaitLogFlush(h->PacketLogger);
4649
4650        ReleaseHub(h);
4651    }
4652}
4653
4654// SecureNAT 設定の読み込み
4655void SiLoadSecureNAT(HUB *h, FOLDER *f)
4656{
4657    VH_OPTION o;
4658    // 引数チェック
4659    if (h == NULL || f == NULL)
4660    {
4661        return;
4662    }
4663
4664    // VH_OPTION を読み込む
4665    NiLoadVhOptionEx(&o, f);
4666
4667    // VH_OPTION をセット
4668    Copy(h->SecureNATOption, &o, sizeof(VH_OPTION));
4669
4670    EnableSecureNAT(h, CfgGetBool(f, "Disabled") ? false : true);
4671}
4672
4673// 仮想レイヤ 3 スイッチ設定の読み込み
4674void SiLoadL3SwitchCfg(L3SW *sw, FOLDER *f)
4675{
4676    UINT i;
4677    FOLDER *if_folder, *table_folder;
4678    TOKEN_LIST *t;
4679    bool active = false;
4680    // 引数チェック
4681    if (sw == NULL || f == NULL)
4682    {
4683        return;
4684    }
4685
4686    active = CfgGetBool(f, "Active");
4687
4688    // インターフェイスリスト
4689    if_folder = CfgGetFolder(f, "InterfaceList");
4690    if (if_folder != NULL)
4691    {
4692        t = CfgEnumFolderToTokenList(if_folder);
4693        if (t != NULL)
4694        {
4695            for (i = 0;i < t->NumTokens;i++)
4696            {
4697                FOLDER *ff = CfgGetFolder(if_folder, t->Token[i]);
4698                char name[MAX_HUBNAME_LEN + 1];
4699                UINT ip, subnet;
4700
4701                CfgGetStr(ff, "HubName", name, sizeof(name));
4702                ip = CfgGetIp32(ff, "IpAddress");
4703                subnet = CfgGetIp32(ff, "SubnetMask");
4704
4705                L3AddIf(sw, name, ip, subnet);
4706            }
4707            FreeToken(t);
4708        }
4709    }
4710
4711    // ルーティングテーブル
4712    table_folder = CfgGetFolder(f, "RoutingTable");
4713    if (table_folder != NULL)
4714    {
4715        t = CfgEnumFolderToTokenList(table_folder);
4716        if (t != NULL)
4717        {
4718            for (i = 0;i < t->NumTokens;i++)
4719            {
4720                FOLDER *ff = CfgGetFolder(table_folder, t->Token[i]);
4721                L3TABLE tbl;
4722
4723                Zero(&tbl, sizeof(tbl));
4724                tbl.NetworkAddress = CfgGetIp32(ff, "NetworkAddress");
4725                tbl.SubnetMask = CfgGetIp32(ff, "SubnetMask");
4726                tbl.GatewayAddress = CfgGetIp32(ff, "GatewayAddress");
4727                tbl.Metric = CfgGetInt(ff, "Metric");
4728
4729                L3AddTable(sw, &tbl);
4730            }
4731            FreeToken(t);
4732        }
4733    }
4734
4735    if (active)
4736    {
4737        L3SwStart(sw);
4738    }
4739}
4740
4741// 仮想レイヤ 3 スイッチ設定の書き込み
4742void SiWriteL3SwitchCfg(FOLDER *f, L3SW *sw)
4743{
4744    UINT i;
4745    FOLDER *if_folder, *table_folder;
4746    char tmp[MAX_SIZE];
4747    // 引数チェック
4748    if (f == NULL || sw == NULL)
4749    {
4750        return;
4751    }
4752
4753    // 動作フラグ
4754    CfgAddBool(f, "Active", sw->Active);
4755
4756    // インターフェイスリスト
4757    if_folder = CfgCreateFolder(f, "InterfaceList");
4758    for (i = 0;i < LIST_NUM(sw->IfList);i++)
4759    {
4760        L3IF *e = LIST_DATA(sw->IfList, i);
4761        FOLDER *ff;
4762
4763        Format(tmp, sizeof(tmp), "Interface%u", i);
4764        ff = CfgCreateFolder(if_folder, tmp);
4765
4766        CfgAddStr(ff, "HubName", e->HubName);
4767        CfgAddIp32(ff, "IpAddress", e->IpAddress);
4768        CfgAddIp32(ff, "SubnetMask", e->SubnetMask);
4769    }
4770
4771    // ルーティングテーブル
4772    table_folder = CfgCreateFolder(f, "RoutingTable");
4773    for (i = 0;i < LIST_NUM(sw->TableList);i++)
4774    {
4775        L3TABLE *e = LIST_DATA(sw->TableList, i);
4776        FOLDER *ff;
4777
4778        Format(tmp, sizeof(tmp), "Entry%u", i);
4779        ff = CfgCreateFolder(table_folder, tmp);
4780
4781        CfgAddIp32(ff, "NetworkAddress", e->NetworkAddress);
4782        CfgAddIp32(ff, "SubnetMask", e->SubnetMask);
4783        CfgAddIp32(ff, "GatewayAddress", e->GatewayAddress);
4784        CfgAddInt(ff, "Metric", e->Metric);
4785    }
4786}
4787
4788// 仮想レイヤ 3 スイッチ一覧の読み込み
4789void SiLoadL3Switchs(SERVER *s, FOLDER *f)
4790{
4791    UINT i;
4792    TOKEN_LIST *t;
4793    CEDAR *c;
4794    // 引数チェック
4795    if (s == NULL || f == NULL)
4796    {
4797        return;
4798    }
4799    c = s->Cedar;
4800
4801    t = CfgEnumFolderToTokenList(f);
4802    if (t != NULL)
4803    {
4804        for (i = 0;i < t->NumTokens;i++)
4805        {
4806            char *name = t->Token[i];
4807            L3SW *sw = L3AddSw(c, name);
4808
4809            SiLoadL3SwitchCfg(sw, CfgGetFolder(f, name));
4810
4811            ReleaseL3Sw(sw);
4812        }
4813    }
4814    FreeToken(t);
4815}
4816
4817// 仮想レイヤ 3 スイッチ一覧の書き込み
4818void SiWriteL3Switchs(FOLDER *f, SERVER *s)
4819{
4820    UINT i;
4821    FOLDER *folder;
4822    CEDAR *c;
4823    // 引数チェック
4824    if (f == NULL || s == NULL)
4825    {
4826        return;
4827    }
4828    c = s->Cedar;
4829
4830    LockList(c->L3SwList);
4831    {
4832        for (i = 0;i < LIST_NUM(c->L3SwList);i++)
4833        {
4834            L3SW *sw = LIST_DATA(c->L3SwList, i);
4835
4836            Lock(sw->lock);
4837            {
4838                folder = CfgCreateFolder(f, sw->Name);
4839
4840                SiWriteL3SwitchCfg(folder, sw);
4841            }
4842            Unlock(sw->lock);
4843        }
4844    }
4845    UnlockList(c->L3SwList);
4846}
4847
4848// ライセンス一覧の書き込み
4849void SiWriteLicenseManager(FOLDER *f, SERVER *s)
4850{
4851    LICENSE_SYSTEM *ss;
4852    // 引数チェック
4853    if (f == NULL || s == NULL)
4854    {
4855        return;
4856    }
4857
4858    ss = s->LicenseSystem;
4859    if (s == NULL)
4860    {
4861        return;
4862    }
4863
4864    LockList(ss->LicenseList);
4865    {
4866        UINT i;
4867        for (i = 0;i < LIST_NUM(ss->LicenseList);i++)
4868        {
4869            LICENSE *e = LIST_DATA(ss->LicenseList, i);
4870            char name[MAX_SIZE];
4871            FOLDER *ff;
4872
4873            Format(name, sizeof(name), "License%u", i);
4874            ff = CfgCreateFolder(f, name);
4875            CfgAddStr(ff, "LicenseKey", e->LicenseKeyStr);
4876            CfgAddInt(ff, "LicenseType", e->ProductId);
4877        }
4878    }
4879    UnlockList(ss->LicenseList);
4880}
4881
4882// ライセンス一覧の読み込み
4883void SiLoadLicenseManager(SERVER *s, FOLDER *f)
4884{
4885    UINT i;
4886    TOKEN_LIST *t;
4887    CEDAR *c;
4888    // 引数チェック
4889    if (s == NULL || f == NULL)
4890    {
4891        return;
4892    }
4893    c = s->Cedar;
4894
4895    t = CfgEnumFolderToTokenList(f);
4896    if (t != NULL)
4897    {
4898        for (i = 0;i < t->NumTokens;i++)
4899        {
4900            char *str = t->Token[i];
4901            FOLDER *ff = CfgGetFolder(f, str);
4902
4903            if (ff != NULL)
4904            {
4905                UINT product_id = CfgGetInt(ff, "LicenseType");
4906                char key[MAX_SIZE];
4907
4908                if (CfgGetStr(ff, "LicenseKey", key, sizeof(key)))
4909                {
4910                    // ライセンス登録
4911                    //LiInputLicenseKeyEx(c, s->LicenseSystem, key, product_id, NULL);
4912                }
4913            }
4914        }
4915    }
4916    FreeToken(t);
4917
4918    DestroyServerCapsCache(s);
4919}
4920
4921// 仮想 HUB 一覧の書き込み
4922void SiWriteHubs(FOLDER *f, SERVER *s)
4923{
4924    UINT i;
4925    FOLDER *hub_folder;
4926    CEDAR *c;
4927    UINT num;
4928    HUB **hubs;
4929    // 引数チェック
4930    if (f == NULL || s == NULL)
4931    {
4932        return;
4933    }
4934    c = s->Cedar;
4935
4936    LockList(c->HubList);
4937    {
4938        hubs = ToArray(c->HubList);
4939        num = LIST_NUM(c->HubList);
4940
4941        for (i = 0;i < num;i++)
4942        {
4943            AddRef(hubs[i]->ref);
4944        }
4945    }
4946    UnlockList(c->HubList);
4947
4948    for (i = 0;i < num;i++)
4949    {
4950        HUB *h = hubs[i];
4951
4952        Lock(h->lock);
4953        {
4954            hub_folder = CfgCreateFolder(f, h->Name);
4955            SiWriteHubCfg(hub_folder, h);
4956        }
4957        Unlock(h->lock);
4958
4959        ReleaseHub(h);
4960
4961        if ((i % 30) == 1)
4962        {
4963            YieldCpu();
4964        }
4965    }
4966
4967    Free(hubs);
4968}
4969
4970// 仮想 HUB 一覧の読み込み
4971void SiLoadHubs(SERVER *s, FOLDER *f)
4972{
4973    UINT i;
4974    FOLDER *hub_folder;
4975    CEDAR *c;
4976    TOKEN_LIST *t;
4977    bool b = false;
4978    // 引数チェック
4979    if (f == NULL || s == NULL)
4980    {
4981        return;
4982    }
4983    c = s->Cedar;
4984
4985    t = CfgEnumFolderToTokenList(f);
4986    for (i = 0;i < t->NumTokens;i++)
4987    {
4988        char *name = t->Token[i];
4989        if (s->Cedar->Bridge)
4990        {
4991            if (StrCmpi(name, SERVER_DEFAULT_BRIDGE_NAME) == 0)
4992            {
4993                // Bridge の場合は "BRIDGE" という名前の仮想 HUB の設定
4994                // しか読み込まない
4995                b = true;
4996            }
4997            else
4998            {
4999                continue;
5000            }
5001        }
5002        hub_folder = CfgGetFolder(f, name);
5003        if (hub_folder != NULL)
5004        {
5005            SiLoadHubCfg(s, hub_folder, name);
5006        }
5007    }
5008    FreeToken(t);
5009
5010    if (s->Cedar->Bridge && b == false)
5011    {
5012        // "BRIDGE" という名前の仮想 HUB の設定が存在しない場合は新たに作成する
5013        SiInitDefaultHubList(s);
5014    }
5015}
5016
5017// サーバー固有の設定の読み込み
5018void SiLoadServerCfg(SERVER *s, FOLDER *f)
5019{
5020    BUF *b;
5021    CEDAR *c;
5022    char tmp[MAX_SIZE];
5023    X *x = NULL;
5024    K *k = NULL;
5025    bool cluster_allowed = false;
5026    UINT num_connections_per_ip = 0;
5027    // 引数チェック
5028    if (s == NULL || f == NULL)
5029    {
5030        return;
5031    }
5032
5033    // 保存間隔関係
5034    s->AutoSaveConfigSpan = CfgGetInt(f, "AutoSaveConfigSpan") * 1000;
5035    if (s->AutoSaveConfigSpan == 0)
5036    {
5037        s->AutoSaveConfigSpan = SERVER_FILE_SAVE_INTERVAL_DEFAULT;
5038    }
5039    else
5040    {
5041        s->AutoSaveConfigSpan = MAKESURE(s->AutoSaveConfigSpan, SERVER_FILE_SAVE_INTERVAL_MIN, SERVER_FILE_SAVE_INTERVAL_MAX);
5042    }
5043
5044    c = s->Cedar;
5045    Lock(c->lock);
5046    {
5047        {
5048            RPC_KEEP k;
5049
5050            // キープアライブ関係
5051            Zero(&k, sizeof(k));
5052            k.UseKeepConnect = CfgGetBool(f, "UseKeepConnect");
5053            CfgGetStr(f, "KeepConnectHost", k.KeepConnectHost, sizeof(k.KeepConnectHost));
5054            k.KeepConnectPort = CfgGetInt(f, "KeepConnectPort");
5055            k.KeepConnectProtocol = CfgGetInt(f, "KeepConnectProtocol");
5056            k.KeepConnectInterval = CfgGetInt(f, "KeepConnectInterval") * 1000;
5057            if (k.KeepConnectPort == 0)
5058            {
5059                k.KeepConnectPort = 80;
5060            }
5061            if (StrLen(k.KeepConnectHost) == 0)
5062            {
5063                StrCpy(k.KeepConnectHost, sizeof(k.KeepConnectHost), CLIENT_DEFAULT_KEEPALIVE_HOST);
5064            }
5065            if (k.KeepConnectInterval == 0)
5066            {
5067                k.KeepConnectInterval = KEEP_INTERVAL_DEFAULT * 1000;
5068            }
5069            if (k.KeepConnectInterval < 5000)
5070            {
5071                k.KeepConnectInterval = 5000;
5072            }
5073            if (k.KeepConnectInterval > 600000)
5074            {
5075                k.KeepConnectInterval = 600000;
5076            }
5077
5078            Lock(s->Keep->lock);
5079            {
5080                KEEP *keep = s->Keep;
5081                keep->Enable = k.UseKeepConnect;
5082                keep->Server = true;
5083                StrCpy(keep->ServerName, sizeof(keep->ServerName), k.KeepConnectHost);
5084                keep->ServerPort = k.KeepConnectPort;
5085                keep->UdpMode = k.KeepConnectProtocol;
5086                keep->Interval = k.KeepConnectInterval;
5087            }
5088            Unlock(s->Keep->lock);
5089        }
5090
5091        // IPv6 リスナーを無効にするかどうか
5092        s->Cedar->DisableIPv6Listener = CfgGetBool(f, "DisableIPv6Listener");
5093
5094        // DeadLock
5095        s->DisableDeadLockCheck = CfgGetBool(f, "DisableDeadLockCheck");
5096
5097        // 自動ファイル削除器
5098        s->Eraser = NewEraser(s->Logger, CfgGetInt64(f, "AutoDeleteCheckDiskFreeSpaceMin"));
5099
5100        // NoLinuxArpFilter
5101        s->NoLinuxArpFilter = CfgGetBool(f, "NoLinuxArpFilter");
5102
5103        // NoHighPriorityProcess
5104        s->NoHighPriorityProcess = CfgGetBool(f, "NoHighPriorityProcess");
5105
5106        // NoDebugDump
5107        s->NoDebugDump = CfgGetBool(f, "NoDebugDump");
5108        if (s->NoDebugDump)
5109        {
5110#ifdef  OS_WIN32
5111            MsSetEnableMinidump(false);
5112#endif  // OS_WIN32
5113        }
5114
5115        // クライアントにシグネチャを送信させない
5116        s->NoSendSignature = CfgGetBool(f, "NoSendSignature");
5117
5118        // デバッグログ
5119        s->SaveDebugLog = CfgGetBool(f, "SaveDebugLog");
5120        if (s->SaveDebugLog)
5121        {
5122            s->DebugLog = NewTinyLog();
5123        }
5124
5125        // サーバー証明書
5126        b = CfgGetBuf(f, "ServerCert");
5127        if (b != NULL)
5128        {
5129            x = BufToX(b, false);
5130            FreeBuf(b);
5131        }
5132
5133        // サーバー秘密鍵
5134        b = CfgGetBuf(f, "ServerKey");
5135        if (b != NULL)
5136        {
5137            k = BufToK(b, true, false, NULL);
5138            FreeBuf(b);
5139        }
5140
5141        if (x == NULL || k == NULL || CheckXandK(x, k) == false)
5142        {
5143            FreeX(x);
5144            FreeK(k);
5145            SiGenerateDefualtCert(&x, &k);
5146
5147            SetCedarCert(c, x, k);
5148
5149            FreeX(x);
5150            FreeK(k);
5151        }
5152        else
5153        {
5154            SetCedarCert(c, x, k);
5155
5156            FreeX(x);
5157            FreeK(k);
5158        }
5159
5160        // 暗号化名
5161        if (CfgGetStr(f, "CipherName", tmp, sizeof(tmp)))
5162        {
5163            StrUpper(tmp);
5164            if (CheckCipherListName(tmp))
5165            {
5166                SetCedarCipherList(c, tmp);
5167            }
5168        }
5169
5170        // トラフィック情報
5171        Lock(c->TrafficLock);
5172        {
5173            SiLoadTraffic(f, "ServerTraffic", c->Traffic);
5174        }
5175        Unlock(c->TrafficLock);
5176
5177        // 現在のライセンスでクラスタモードが許可されているかどうかを取得する
5178        cluster_allowed = false;
5179        if (s->Cedar->Bridge == false)
5180        {
5181            LICENSE_STATUS status;
5182
5183            LiParseCurrentLicenseStatus(s->LicenseSystem, &status);
5184
5185            if (status.AllowEnterpriseFunction)
5186            {
5187                cluster_allowed = true;
5188            }
5189        }
5190
5191        // サーバーの種類
5192        s->UpdatedServerType = s->ServerType = 
5193            cluster_allowed ? CfgGetInt(f, "ServerType") : SERVER_TYPE_STANDALONE;
5194
5195        // パスワード
5196        if (CfgGetByte(f, "HashedPassword", s->HashedPassword, sizeof(s->HashedPassword)) != sizeof(s->HashedPassword))
5197        {
5198            Hash(s->HashedPassword, "", 0, true);
5199        }
5200
5201        if (s->ServerType != SERVER_TYPE_STANDALONE)
5202        {
5203            // サーバーの性能基準比
5204            s->Weight = CfgGetInt(f, "ClusterMemberWeight");
5205            if (s->Weight == 0)
5206            {
5207                s->Weight = FARM_DEFAULT_WEIGHT;
5208            }
5209        }
5210        else
5211        {
5212            s->Weight = FARM_DEFAULT_WEIGHT;
5213        }
5214
5215        if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
5216        {
5217            s->ControllerOnly = CfgGetBool(f, "ControllerOnly");
5218        }
5219
5220        if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
5221        {
5222            char tmp[6 * MAX_PUBLIC_PORT_NUM + 1];
5223            // ファームメンバの場合の設定項目の読み込み
5224            CfgGetStr(f, "ControllerName", s->ControllerName, sizeof(s->ControllerName));
5225            s->ControllerPort = CfgGetInt(f, "ControllerPort");
5226            CfgGetByte(f, "MemberPassword", s->MemberPassword, SHA1_SIZE);
5227            s->PublicIp = CfgGetIp32(f, "PublicIp");
5228            if (CfgGetStr(f, "PublicPorts", tmp, sizeof(tmp)))
5229            {
5230                TOKEN_LIST *t = ParseToken(tmp, ", ");
5231                UINT i;
5232                s->NumPublicPort = t->NumTokens;
5233                s->PublicPorts = ZeroMalloc(s->NumPublicPort * sizeof(UINT));
5234                for (i = 0;i < s->NumPublicPort;i++)
5235                {
5236                    s->PublicPorts[i] = ToInt(t->Token[i]);
5237                }
5238                FreeToken(t);
5239            }
5240        }
5241    }
5242    Unlock(c->lock);
5243}
5244
5245// サーバー固有の設定の書き込み
5246void SiWriteServerCfg(FOLDER *f, SERVER *s)
5247{
5248    BUF *b;
5249    CEDAR *c;
5250    // 引数チェック
5251    if (f == NULL || s == NULL)
5252    {
5253        return;
5254    }
5255
5256    CfgAddInt(f, "AutoSaveConfigSpan", s->AutoSaveConfigSpan / 1000);
5257
5258    c = s->Cedar;
5259
5260    Lock(c->lock);
5261    {
5262        Lock(s->Keep->lock);
5263        {
5264            KEEP *k = s->Keep;
5265            CfgAddBool(f, "UseKeepConnect", k->Enable);
5266            CfgAddStr(f, "KeepConnectHost", k->ServerName);
5267            CfgAddInt(f, "KeepConnectPort", k->ServerPort);
5268            CfgAddInt(f, "KeepConnectProtocol", k->UdpMode);
5269            CfgAddInt(f, "KeepConnectInterval", k->Interval / 1000);
5270        }
5271        Unlock(s->Keep->lock);
5272
5273        // IPv6 リスナー無効化設定
5274        CfgAddBool(f, "DisableIPv6Listener", s->Cedar->DisableIPv6Listener);
5275
5276        // DeadLock
5277        CfgAddBool(f, "DisableDeadLockCheck", s->DisableDeadLockCheck);
5278
5279        // 自動ファイル削除器関係
5280        CfgAddInt64(f, "AutoDeleteCheckDiskFreeSpaceMin", s->Eraser->MinFreeSpace);
5281
5282        // NoLinuxArpFilter
5283        if (GetOsInfo()->OsType == OSTYPE_LINUX)
5284        {
5285            CfgAddBool(f, "NoLinuxArpFilter", s->NoLinuxArpFilter);
5286        }
5287
5288        // NoHighPriorityProcess
5289        CfgAddBool(f, "NoHighPriorityProcess", s->NoHighPriorityProcess);
5290
5291#ifdef  OS_WIN32
5292        CfgAddBool(f, "NoDebugDump", s->NoDebugDump);
5293#endif  // OS_WIN32
5294
5295        // デバッグログ
5296        CfgAddBool(f, "SaveDebugLog", s->SaveDebugLog);
5297
5298        // クライアントにシグネチャを送信させない
5299        CfgAddBool(f, "NoSendSignature", s->NoSendSignature);
5300
5301        // サーバー証明書
5302        b = XToBuf(c->ServerX, false);
5303        CfgAddBuf(f, "ServerCert", b);
5304        FreeBuf(b);
5305
5306        // サーバー秘密鍵
5307        b = KToBuf(c->ServerK, false, NULL);
5308        CfgAddBuf(f, "ServerKey", b);
5309        FreeBuf(b);
5310
5311        // トラフィック情報
5312        Lock(c->TrafficLock);
5313        {
5314            SiWriteTraffic(f, "ServerTraffic", c->Traffic);
5315        }
5316        Unlock(c->TrafficLock);
5317
5318        // サーバーの種類
5319        if (s->Cedar->Bridge == false)
5320        {
5321            CfgAddInt(f, "ServerType", s->UpdatedServerType);
5322        }
5323
5324        // 暗号化
5325        CfgAddStr(f, "CipherName", s->Cedar->CipherList);
5326
5327        // パスワード
5328        CfgAddByte(f, "HashedPassword", s->HashedPassword, sizeof(s->HashedPassword));
5329
5330        if (s->UpdatedServerType == SERVER_TYPE_FARM_MEMBER)
5331        {
5332            char tmp[6 * MAX_PUBLIC_PORT_NUM + 1];
5333            UINT i;
5334            // ファームメンバの場合の設定項目
5335            CfgAddStr(f, "ControllerName", s->ControllerName);
5336            CfgAddInt(f, "ControllerPort", s->ControllerPort);
5337            CfgAddByte(f, "MemberPassword", s->MemberPassword, SHA1_SIZE);
5338            CfgAddIp32(f, "PublicIp", s->PublicIp);
5339            tmp[0] = 0;
5340            for (i = 0;i < s->NumPublicPort;i++)
5341            {
5342                char tmp2[MAX_SIZE];
5343                ToStr(tmp2, s->PublicPorts[i]);
5344                StrCat(tmp, sizeof(tmp), tmp2);
5345                StrCat(tmp, sizeof(tmp), ",");
5346            }
5347            if (StrLen(tmp) >= 1)
5348            {
5349                if (tmp[StrLen(tmp) - 1] == ',')
5350                {
5351                    tmp[StrLen(tmp) - 1] = 0;
5352                }
5353            }
5354            CfgAddStr(f, "PublicPorts", tmp);
5355        }
5356
5357        if (s->UpdatedServerType != SERVER_TYPE_STANDALONE)
5358        {
5359            CfgAddInt(f, "ClusterMemberWeight", s->Weight);
5360        }
5361
5362        if (s->UpdatedServerType == SERVER_TYPE_FARM_CONTROLLER)
5363        {
5364            CfgAddBool(f, "ControllerOnly", s->ControllerOnly);
5365        }
5366    }
5367    Unlock(c->lock);
5368}
5369
5370// トラフィック情報の読み込み
5371void SiLoadTraffic(FOLDER *parent, char *name, TRAFFIC *t)
5372{
5373    FOLDER *f;
5374    // 引数チェック
5375    if (t != NULL)
5376    {
5377        Zero(t, sizeof(TRAFFIC));
5378    }
5379    if (parent == NULL || name == NULL || t == NULL)
5380    {
5381        return;
5382    }
5383
5384    f = CfgGetFolder(parent, name);
5385
5386    if (f == NULL)
5387    {
5388        return;
5389    }
5390
5391    SiLoadTrafficInner(f, "SendTraffic", &t->Send);
5392    SiLoadTrafficInner(f, "RecvTraffic", &t->Recv);
5393}
5394void SiLoadTrafficInner(FOLDER *parent, char *name, TRAFFIC_ENTRY *e)
5395{
5396    FOLDER *f;
5397    // 引数チェック
5398    if (e != NULL)
5399    {
5400        Zero(e, sizeof(TRAFFIC_ENTRY));
5401    }
5402    if (parent == NULL || name == NULL || e == NULL)
5403    {
5404        return;
5405    }
5406
5407    f = CfgGetFolder(parent, name);
5408    if (f == NULL)
5409    {
5410        return;
5411    }
5412
5413    e->BroadcastCount = CfgGetInt64(f, "BroadcastCount");
5414    e->BroadcastBytes = CfgGetInt64(f, "BroadcastBytes");
5415    e->UnicastCount = CfgGetInt64(f, "UnicastCount");
5416    e->UnicastBytes = CfgGetInt64(f, "UnicastBytes");
5417}
5418
5419// トラフィック情報の書き込み
5420void SiWriteTraffic(FOLDER *parent, char *name, TRAFFIC *t)
5421{
5422    FOLDER *f;
5423    // 引数チェック
5424    if (parent == NULL || name == NULL || t == NULL)
5425    {
5426        return;
5427    }
5428
5429    f = CfgCreateFolder(parent, name);
5430
5431    SiWriteTrafficInner(f, "SendTraffic", &t->Send);
5432    SiWriteTrafficInner(f, "RecvTraffic", &t->Recv);
5433}
5434void SiWriteTrafficInner(FOLDER *parent, char *name, TRAFFIC_ENTRY *e)
5435{
5436    FOLDER *f;
5437    // 引数チェック
5438    if (parent == NULL || name == NULL || e == NULL)
5439    {
5440        return;
5441    }
5442
5443    f = CfgCreateFolder(parent, name);
5444    CfgAddInt64(f, "BroadcastCount", e->BroadcastCount);
5445    CfgAddInt64(f, "BroadcastBytes", e->BroadcastBytes);
5446    CfgAddInt64(f, "UnicastCount", e->UnicastCount);
5447    CfgAddInt64(f, "UnicastBytes", e->UnicastBytes);
5448}
5449
5450// 設定ファイル書き込み用スレッド
5451void SiSaverThread(THREAD *thread, void *param)
5452{
5453    SERVER *s = (SERVER *)param;
5454    // 引数チェック
5455    if (thread == NULL || param == NULL)
5456    {
5457        return;
5458    }
5459
5460    while (s->Halt == false)
5461    {
5462        // 設定ファイル保存
5463        SiWriteConfigurationFile(s);
5464
5465        Wait(s->SaveHaltEvent, s->AutoSaveConfigSpan);
5466    }
5467}
5468
5469// 設定ファイルに書き込む
5470UINT SiWriteConfigurationFile(SERVER *s)
5471{
5472    UINT ret;
5473    // 引数チェック
5474    if (s == NULL)
5475    {
5476        return 0;
5477    }
5478
5479    if (s->CfgRw == NULL)
5480    {
5481        return 0;
5482    }
5483
5484    Lock(s->SaveCfgLock);
5485    {
5486        FOLDER *f;
5487
5488        Debug("save: SiWriteConfigurationToCfg() start.\n");
5489        f = SiWriteConfigurationToCfg(s);
5490        Debug("save: SiWriteConfigurationToCfg() finished.\n");
5491
5492        Debug("save: SaveCfgRw() start.\n");
5493        ret = SaveCfgRw(s->CfgRw, f);
5494        Debug("save: SaveCfgRw() finished.\n");
5495
5496        Debug("save: CfgDeleteFolder() start.\n");
5497        CfgDeleteFolder(f);
5498        Debug("save: CfgDeleteFolder() finished.\n");
5499    }
5500    Unlock(s->SaveCfgLock);
5501
5502    return ret;
5503}
5504
5505// コンフィグレーション解放
5506void SiFreeConfiguration(SERVER *s)
5507{
5508    // 引数チェック
5509    if (s == NULL)
5510    {
5511        return;
5512    }
5513
5514    // 設定ファイルに書き込む
5515    SiWriteConfigurationFile(s);
5516
5517    // 設定ファイル保存スレッドの終了
5518    s->Halt = true;
5519    Set(s->SaveHaltEvent);
5520    WaitThread(s->SaveThread, INFINITE);
5521
5522    ReleaseEvent(s->SaveHaltEvent);
5523    ReleaseThread(s->SaveThread);
5524
5525    FreeCfgRw(s->CfgRw);
5526    s->CfgRw = NULL;
5527
5528    // Ethernet 解放
5529    FreeEth();
5530}
5531
5532// StXxx 関係関数の初期化
5533void StInit()
5534{
5535    if (server_lock != NULL)
5536    {
5537        return;
5538    }
5539
5540    server_lock = NewLock();
5541}
5542
5543// StXxx 関係関数の解放
5544void StFree()
5545{
5546    DeleteLock(server_lock);
5547    server_lock = NULL;
5548}
5549
5550// サーバーの開始
5551void StStartServer(bool bridge)
5552{
5553    Lock(server_lock);
5554    {
5555        if (server != NULL)
5556        {
5557            // すでに開始されている
5558            Unlock(server_lock);
5559            return;
5560        }
5561
5562        // サーバーの作成
5563        server = SiNewServer(bridge);
5564    }
5565    Unlock(server_lock);
5566
5567//  StartCedarLog();
5568}
5569
5570// サーバーの取得
5571SERVER *StGetServer()
5572{
5573    if (server == NULL)
5574    {
5575        return NULL;
5576    }
5577    return server;
5578}
5579
5580// サーバーの停止
5581void StStopServer()
5582{
5583    Lock(server_lock);
5584    {
5585        if (server == NULL)
5586        {
5587            // 開始されていない
5588            Unlock(server_lock);
5589            return;
5590        }
5591
5592        // サーバーの解放
5593        SiReleaseServer(server);
5594        server = NULL;
5595    }
5596    Unlock(server_lock);
5597
5598    StopCedarLog();
5599}
5600
5601// サーバーの種類の設定
5602void SiSetServerType(SERVER *s, UINT type,
5603                     UINT ip, UINT num_port, UINT *ports,
5604                     char *controller_name, UINT controller_port, UCHAR *password, UINT weight, bool controller_only)
5605{
5606    bool bridge;
5607    // 引数チェック
5608    if (s == NULL)
5609    {
5610        return;
5611    }
5612    if (type == SERVER_TYPE_FARM_MEMBER &&
5613        (num_port == 0 || ports == NULL || controller_name == NULL ||
5614        controller_port == 0 || password == NULL || num_port > MAX_PUBLIC_PORT_NUM))
5615    {
5616        return;
5617    }
5618    if (weight == 0)
5619    {
5620        weight = FARM_DEFAULT_WEIGHT;
5621    }
5622
5623    bridge = s->Cedar->Bridge;
5624
5625    Lock(s->lock);
5626    {
5627        // 種類の更新
5628        s->UpdatedServerType = type;
5629
5630        s->Weight = weight;
5631
5632        // 値の設定
5633        if (type == SERVER_TYPE_FARM_MEMBER)
5634        {
5635            StrCpy(s->ControllerName, sizeof(s->ControllerName), controller_name);
5636            s->ControllerPort = controller_port;
5637            if (IsZero(password, SHA1_SIZE) == false)
5638            {
5639                Copy(s->MemberPassword, password, SHA1_SIZE);
5640            }
5641            s->PublicIp = ip;
5642            s->NumPublicPort = num_port;
5643            if (s->PublicPorts != NULL)
5644            {
5645                Free(s->PublicPorts);
5646            }
5647            s->PublicPorts = ZeroMalloc(num_port * sizeof(UINT));
5648            Copy(s->PublicPorts, ports, num_port * sizeof(UINT));
5649        }
5650
5651        if (type == SERVER_TYPE_FARM_CONTROLLER)
5652        {
5653            s->ControllerOnly = controller_only;
5654        }
5655    }
5656    Unlock(s->lock);
5657
5658    // サーバーの再起動
5659    SiRebootServer(bridge);
5660}
5661
5662// サーバーの再起動スレッド
5663void SiRebootServerThread(THREAD *thread, void *param)
5664{
5665    // 引数チェック
5666    if (thread == NULL)
5667    {
5668        return;
5669    }
5670
5671    if (server == NULL)
5672    {
5673        return;
5674    }
5675
5676    // サーバーの停止
5677    StStopServer();
5678
5679    // サーバーの開始
5680    StStartServer((bool)param);
5681}
5682
5683// サーバーの再起動
5684void SiRebootServer(bool bridge)
5685{
5686    SiRebootServerEx(bridge, false);
5687}
5688void SiRebootServerEx(bool bridge, bool reset_setting)
5689{
5690    THREAD *t;
5691
5692    server_reset_setting = reset_setting;
5693
5694    t = NewThread(SiRebootServerThread, (void *)bridge);
5695    ReleaseThread(t);
5696}
5697
5698// すべてのリスナーの停止
5699void SiStopAllListener(SERVER *s)
5700{
5701    // 引数チェック
5702    if (s == NULL)
5703    {
5704        return;
5705    }
5706
5707    SiLockListenerList(s);
5708    {
5709        UINT i;
5710        LIST *o = NewListFast(NULL);
5711        for (i = 0;i < LIST_NUM(s->ServerListenerList);i++)
5712        {
5713            SERVER_LISTENER *e = LIST_DATA(s->ServerListenerList, i);
5714            Add(o, e);
5715        }
5716
5717        for (i = 0;i < LIST_NUM(o);i++)
5718        {
5719            SERVER_LISTENER *e = LIST_DATA(o, i);
5720            SiDeleteListener(s, e->Port);
5721        }
5722
5723        ReleaseList(o);
5724    }
5725    SiUnlockListenerList(s);
5726
5727    ReleaseList(s->ServerListenerList);
5728}
5729
5730// サーバーのクリーンアップ
5731void SiCleanupServer(SERVER *s)
5732{
5733    UINT i;
5734    CEDAR *c;
5735    LISTENER **listener_list;
5736    UINT num_listener;
5737    HUB **hub_list;
5738    UINT num_hub;
5739    // 引数チェック
5740    if (s == NULL)
5741    {
5742        return;
5743    }
5744
5745    SiFreeDeadLockCheck(s);
5746
5747    FreeServerSnapshot(s);
5748
5749    c = s->Cedar;
5750
5751    if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
5752    {
5753        // ファームメンバの場合、ファームコントローラへの接続を停止
5754        SLog(c, "LS_STOP_FARM_MEMBER");
5755        SiStopConnectToController(s->FarmController);
5756        s->FarmController = NULL;
5757        SLog(c, "LS_STOP_FARM_MEMBER_2");
5758    }
5759
5760    IncrementServerConfigRevision(s);
5761
5762    SLog(c, "LS_END_2");
5763
5764    SLog(c, "LS_STOP_ALL_LISTENER");
5765    // すべてのリスナーを停止
5766    LockList(c->ListenerList);
5767    {
5768        listener_list = ToArray(c->ListenerList);
5769        num_listener = LIST_NUM(c->ListenerList);
5770        for (i = 0;i < num_listener;i++)
5771        {
5772            AddRef(listener_list[i]->ref);
5773        }
5774    }
5775    UnlockList(c->ListenerList);
5776
5777    for (i = 0;i < num_listener;i++)
5778    {
5779        StopListener(listener_list[i]);
5780        ReleaseListener(listener_list[i]);
5781    }
5782    Free(listener_list);
5783    SLog(c, "LS_STOP_ALL_LISTENER_2");
5784
5785    SLog(c, "LS_STOP_ALL_HUB");
5786    // すべての HUB を停止
5787    LockList(c->HubList);
5788    {
5789        hub_list = ToArray(c->HubList);
5790        num_hub = LIST_NUM(c->HubList);
5791        for (i = 0;i < num_hub;i++)
5792        {
5793            AddRef(hub_list[i]->ref);
5794        }
5795    }
5796    UnlockList(c->HubList);
5797
5798    for (i = 0;i < num_hub;i++)
5799    {
5800        StopHub(hub_list[i]);
5801        ReleaseHub(hub_list[i]);
5802    }
5803    Free(hub_list);
5804    SLog(c, "LS_STOP_ALL_HUB_2");
5805
5806    // コンフィグレーション解放
5807    SiFreeConfiguration(s);
5808
5809    // Cedar の停止
5810    SLog(c, "LS_STOP_CEDAR");
5811    StopCedar(s->Cedar);
5812    SLog(c, "LS_STOP_CEDAR_2");
5813
5814    // すべてのリスナーの停止
5815    SiStopAllListener(s);
5816
5817    if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
5818    {
5819        // ファームコントローラの場合
5820        UINT i;
5821
5822        SLog(c, "LS_STOP_FARM_CONTROL");
5823
5824        // ファームコントロールを停止
5825        SiStopFarmControl(s);
5826
5827        // ファームメンバ情報を解放
5828        ReleaseList(s->FarmMemberList);
5829        s->FarmMemberList = NULL;
5830
5831        for (i = 0;i < LIST_NUM(s->Me->HubList);i++)
5832        {
5833            Free(LIST_DATA(s->Me->HubList, i));
5834        }
5835        ReleaseList(s->Me->HubList);
5836
5837        Free(s->Me);
5838
5839        SLog(c, "LS_STOP_FARM_CONTROL_2");
5840    }
5841
5842    if (s->PublicPorts != NULL)
5843    {
5844        Free(s->PublicPorts);
5845    }
5846
5847    SLog(s->Cedar, "LS_END_1");
5848    SLog(s->Cedar, "L_LINE");
5849
5850    ReleaseCedar(s->Cedar);
5851    DeleteLock(s->lock);
5852    DeleteLock(s->SaveCfgLock);
5853
5854    StopKeep(s->Keep);
5855
5856    FreeEraser(s->Eraser);
5857
5858    // ライセンスシステム解放
5859    if (s->LicenseSystem != NULL)
5860    {
5861        LiFreeLicenseSystem(s->LicenseSystem);
5862    }
5863
5864    FreeLog(s->Logger);
5865
5866    FreeServerCapsCache(s);
5867
5868    SiFreeHubCreateHistory(s);
5869
5870    // デバッグログの停止
5871    FreeTinyLog(s->DebugLog);
5872
5873    DeleteLock(s->TasksFromFarmControllerLock);
5874
5875    Free(s);
5876}
5877
5878// サーバーの解放
5879void SiReleaseServer(SERVER *s)
5880{
5881    // 引数チェック
5882    if (s == NULL)
5883    {
5884        return;
5885    }
5886
5887    if (Release(s->ref) == 0)
5888    {
5889        SiCleanupServer(s);
5890    }
5891}
5892
5893// 次に処理をさせるファームメンバーを指定する
5894FARM_MEMBER *SiGetNextFarmMember(SERVER *s)
5895{
5896    UINT i, num;
5897    UINT min_point = 0;
5898    FARM_MEMBER *ret = NULL;
5899    // 引数チェック
5900    if (s == NULL || s->ServerType != SERVER_TYPE_FARM_CONTROLLER)
5901    {
5902        return NULL;
5903    }
5904
5905    num = LIST_NUM(s->FarmMemberList);
5906    if (num == 0)
5907    {
5908        return NULL;
5909    }
5910
5911    for (i = 0;i < num;i++)
5912    {
5913        UINT num_sessions;
5914        UINT max_sessions;
5915        FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
5916        if (s->ControllerOnly)
5917        {
5918            if (f->Me)
5919            {
5920                // ControllerOnly のとき自分自身は選定しない
5921                continue;
5922            }
5923        }
5924
5925        if (f->Me == false)
5926        {
5927            num_sessions = f->NumSessions;
5928            max_sessions = f->MaxSessions;
5929        }
5930        else
5931        {
5932            num_sessions = Count(s->Cedar->CurrentSessions);
5933            max_sessions = GetServerCapsInt(s, "i_max_sessions");
5934        }
5935
5936        if (max_sessions == 0)
5937        {
5938            max_sessions = GetServerCapsInt(s, "i_max_sessions");
5939        }
5940
5941        if (num_sessions < max_sessions)
5942        {
5943            if (f->Point >= min_point)
5944            {
5945                min_point = f->Point;
5946                ret = f;
5947            }
5948        }
5949    }
5950
5951    return ret;
5952}
5953
5954// HUB 列挙指令受信
5955void SiCalledEnumHub(SERVER *s, PACK *p, PACK *req)
5956{
5957    UINT i;
5958    CEDAR *c;
5959    LICENSE_STATUS st;
5960    UINT num = 0;
5961    // 引数チェック
5962    if (s == NULL || p == NULL || req == NULL)
5963    {
5964        return;
5965    }
5966
5967    LiParseCurrentLicenseStatus(s->LicenseSystem, &st);
5968
5969    c = s->Cedar;
5970
5971    LockList(c->HubList);
5972    {
5973        UINT num = LIST_NUM(c->HubList);
5974        for (i = 0;i < num;i++)
5975        {
5976            HUB *h = LIST_DATA(c->HubList, i);
5977            Lock(h->lock);
5978            {
5979                PackAddStrEx(p, "HubName", h->Name, i, num);
5980                PackAddIntEx(p, "HubType", h->Type, i, num);
5981                PackAddIntEx(p, "NumSession", Count(h->NumSessions), i, num);
5982
5983                PackAddIntEx(p, "NumSessions", LIST_NUM(h->SessionList), i, num);
5984                PackAddIntEx(p, "NumSessionsClient", Count(h->NumSessionsClient), i, num);
5985                PackAddIntEx(p, "NumSessionsBridge", Count(h->NumSessionsBridge), i, num);
5986
5987                PackAddIntEx(p, "NumMacTables", LIST_NUM(h->MacTable), i, num);
5988
5989                PackAddIntEx(p, "NumIpTables", LIST_NUM(h->IpTable), i, num);
5990
5991                PackAddInt64Ex(p, "LastCommTime", h->LastCommTime, i, num);
5992                PackAddInt64Ex(p, "CreatedTime", h->CreatedTime, i, num);
5993            }
5994            Unlock(h->lock);
5995        }
5996    }
5997    UnlockList(c->HubList);
5998
5999    PackAddInt(p, "Point", SiGetPoint(s));
6000    PackAddInt(p, "NumTcpConnections", Count(s->Cedar->CurrentTcpConnections));
6001    PackAddInt(p, "NumTotalSessions", Count(s->Cedar->CurrentSessions));
6002    PackAddInt(p, "MaxSessions", GetServerCapsInt(s, "i_max_sessions"));
6003
6004    PackAddInt(p, "AssignedClientLicense", Count(s->Cedar->AssignedClientLicense));
6005    PackAddInt(p, "AssignedBridgeLicense", Count(s->Cedar->AssignedBridgeLicense));
6006
6007    PackAddData(p, "RandomKey", s->MyRandomKey, SHA1_SIZE);
6008    PackAddInt64(p, "SystemId", st.SystemId);
6009
6010    Lock(c->TrafficLock);
6011    {
6012        OutRpcTraffic(p, c->Traffic);
6013    }
6014    Unlock(c->TrafficLock);
6015
6016    LockList(c->TrafficDiffList);
6017    {
6018        UINT num = LIST_NUM(c->TrafficDiffList);
6019        UINT i;
6020
6021        for (i = 0;i < num;i++)
6022        {
6023            TRAFFIC_DIFF *d = LIST_DATA(c->TrafficDiffList, i);
6024
6025            PackAddIntEx(p, "TdType", d->Type, i, num);
6026            PackAddStrEx(p, "TdHubName", d->HubName, i, num);
6027            PackAddStrEx(p, "TdName", d->Name, i, num);
6028
6029            OutRpcTrafficEx(&d->Traffic, p, i, num);
6030
6031            Free(d->HubName);
6032            Free(d->Name);
6033            Free(d);
6034        }
6035
6036        DeleteAll(c->TrafficDiffList);
6037    }
6038    UnlockList(c->TrafficDiffList);
6039}
6040
6041// HUB 削除指令受信
6042void SiCalledDeleteHub(SERVER *s, PACK *p)
6043{
6044    char name[MAX_SIZE];
6045    HUB *h;
6046    // 引数チェック
6047    if (s == NULL || p == NULL)
6048    {
6049        return;
6050    }
6051
6052    if (PackGetStr(p, "HubName", name, sizeof(name)) == false)
6053    {
6054        return;
6055    }
6056
6057    LockHubList(s->Cedar);
6058
6059    h = GetHub(s->Cedar, name);
6060    if (h == NULL)
6061    {
6062        UnlockHubList(s->Cedar);
6063        return;
6064    }
6065    UnlockHubList(s->Cedar);
6066
6067    SetHubOffline(h);
6068
6069    LockHubList(s->Cedar);
6070
6071    DelHubEx(s->Cedar, h, true);
6072
6073    UnlockHubList(s->Cedar);
6074
6075    ReleaseHub(h);
6076}
6077
6078// HUB 更新指令受信
6079void SiCalledUpdateHub(SERVER *s, PACK *p)
6080{
6081    char name[MAX_SIZE];
6082    UINT type;
6083    HUB_OPTION o;
6084    HUB_LOG log;
6085    bool save_packet_log;
6086    UINT packet_log_switch_type;
6087    UINT packet_log_config[NUM_PACKET_LOG];
6088    bool save_security_log;
6089    bool type_changed = false;
6090    UINT security_log_switch_type;
6091    UINT i;
6092    HUB *h;
6093    // 引数チェック
6094    if (s == NULL || p == NULL)
6095    {
6096        return;
6097    }
6098
6099    PackGetStr(p, "HubName", name, sizeof(name));
6100    type = PackGetInt(p, "HubType");
6101    Zero(&o, sizeof(o));
6102    o.MaxSession = PackGetInt(p, "MaxSession");
6103    o.NoArpPolling = PackGetBool(p, "NoArpPolling");
6104    o.NoIPv6AddrPolling = PackGetBool(p, "NoIPv6AddrPolling");
6105    o.FilterPPPoE = PackGetBool(p, "FilterPPPoE");
6106    o.YieldAfterStorePacket = PackGetBool(p, "YieldAfterStorePacket");
6107    o.NoSpinLockForPacketDelay = PackGetBool(p, "NoSpinLockForPacketDelay");
6108    o.BroadcastStormDetectionThreshold = PackGetInt(p, "BroadcastStormDetectionThreshold");
6109    o.ClientMinimumRequiredBuild = PackGetInt(p, "ClientMinimumRequiredBuild");
6110    o.FixForDLinkBPDU = PackGetBool(p, "FixForDLinkBPDU");
6111    o.NoLookBPDUBridgeId = PackGetBool(p, "NoLookBPDUBridgeId");
6112    o.NoManageVlanId = PackGetBool(p, "NoManageVlanId");
6113    o.VlanTypeId = PackGetInt(p, "VlanTypeId");
6114    if (o.VlanTypeId == 0)
6115    {
6116        o.VlanTypeId = MAC_PROTO_TAGVLAN;
6117    }
6118    o.FilterOSPF = PackGetBool(p, "FilterOSPF");
6119    o.FilterIPv4 = PackGetBool(p, "FilterIPv4");
6120    o.FilterIPv6 = PackGetBool(p, "FilterIPv6");
6121    o.FilterNonIP = PackGetBool(p, "FilterNonIP");
6122    o.NoIPv4PacketLog = PackGetBool(p, "NoIPv4PacketLog");
6123    o.NoIPv6PacketLog = PackGetBool(p, "NoIPv6PacketLog");
6124    o.FilterBPDU = PackGetBool(p, "FilterBPDU");
6125    o.NoIPv6DefaultRouterInRAWhenIPv6 = PackGetBool(p, "NoIPv6DefaultRouterInRAWhenIPv6");
6126    o.NoMacAddressLog = PackGetBool(p, "NoMacAddressLog");
6127    o.ManageOnlyPrivateIP = PackGetBool(p, "ManageOnlyPrivateIP");
6128    o.ManageOnlyLocalUnicastIPv6 = PackGetBool(p, "ManageOnlyLocalUnicastIPv6");
6129    o.DisableIPParsing = PackGetBool(p, "DisableIPParsing");
6130    o.NoIpTable = PackGetBool(p, "NoIpTable");
6131    o.NoEnum = PackGetBool(p, "NoEnum");
6132    save_packet_log = PackGetInt(p, "SavePacketLog");
6133    packet_log_switch_type = PackGetInt(p, "PacketLogSwitchType");
6134    for (i = 0;i < NUM_PACKET_LOG;i++)
6135    {
6136        packet_log_config[i] = PackGetIntEx(p, "PacketLogConfig", i);
6137    }
6138    save_security_log = PackGetInt(p, "SaveSecurityLog");
6139    security_log_switch_type = PackGetInt(p, "SecurityLogSwitchType");
6140
6141    Zero(&log, sizeof(log));
6142    log.SavePacketLog = save_packet_log;
6143    log.PacketLogSwitchType = packet_log_switch_type;
6144    Copy(log.PacketLogConfig, packet_log_config, sizeof(log.PacketLogConfig));
6145    log.SaveSecurityLog = save_security_log;
6146    log.SecurityLogSwitchType = security_log_switch_type;
6147
6148    h = GetHub(s->Cedar, name);
6149    if (h == NULL)
6150    {
6151        return;
6152    }
6153
6154    h->FarmMember_MaxSessionClient = PackGetInt(p, "MaxSessionClient");
6155    h->FarmMember_MaxSessionBridge = PackGetInt(p, "MaxSessionBridge");
6156    h->FarmMember_MaxSessionClientBridgeApply = PackGetBool(p, "MaxSessionClientBridgeApply");
6157
6158    if (h->FarmMember_MaxSessionClientBridgeApply == false)
6159    {
6160        h->FarmMember_MaxSessionClient = INFINITE;
6161        h->FarmMember_MaxSessionBridge = INFINITE;
6162    }
6163
6164    Lock(h->lock);
6165    {
6166        Copy(h->Option, &o, sizeof(HUB_OPTION));
6167        PackGetData2(p, "SecurePassword", h->SecurePassword, SHA1_SIZE);
6168        PackGetData2(p, "HashedPassword", h->HashedPassword, SHA1_SIZE);
6169    }
6170    Unlock(h->lock);
6171
6172    SetHubLogSetting(h, &log);
6173
6174    if (h->Type != type)
6175    {
6176        h->Type = type;
6177        type_changed = true;
6178    }
6179
6180    LockList(h->AccessList);
6181    {
6182        UINT i;
6183        for (i = 0;i < LIST_NUM(h->AccessList);i++)
6184        {
6185            ACCESS *a = LIST_DATA(h->AccessList, i);
6186            Free(a);
6187        }
6188        DeleteAll(h->AccessList);
6189    }
6190    UnlockList(h->AccessList);
6191
6192    for (i = 0;i < SiNumAccessFromPack(p);i++)
6193    {
6194        ACCESS *a = SiPackToAccess(p, i);
6195        AddAccessList(h, a);
6196        Free(a);
6197    }
6198
6199    if (PackGetBool(p, "EnableSecureNAT"))
6200    {
6201        VH_OPTION t;
6202        bool changed;
6203
6204        InVhOption(&t, p);
6205
6206        changed = Cmp(h->SecureNATOption, &t, sizeof(VH_OPTION)) == 0 ? false : true;
6207        Copy(h->SecureNATOption, &t, sizeof(VH_OPTION));
6208
6209        EnableSecureNAT(h, true);
6210
6211        if (changed)
6212        {
6213            Lock(h->lock_online);
6214            {
6215                if (h->SecureNAT != NULL)
6216                {
6217                    SetVirtualHostOption(h->SecureNAT->Nat->Virtual, &t);
6218                    Debug("SiCalledUpdateHub: SecureNAT Updated.\n");
6219                }
6220            }
6221            Unlock(h->lock_online);
6222        }
6223    }
6224    else
6225    {
6226        EnableSecureNAT(h, false);
6227        Debug("SiCalledUpdateHub: SecureNAT Disabled.\n");
6228    }
6229
6230    if (type_changed)
6231    {
6232        // HUB の種類が変更されたのですべてのセッションを削除する
6233        if (h->Offline == false)
6234        {
6235            SetHubOffline(h);
6236            SetHubOnline(h);
6237        }
6238    }
6239
6240    ReleaseHub(h);
6241}
6242
6243// チケットの検査
6244bool SiCheckTicket(HUB *h, UCHAR *ticket, char *username, UINT username_size, char *usernamereal, UINT usernamereal_size, POLICY *policy, char *sessionname, UINT sessionname_size, char *groupname, UINT groupname_size)
6245{
6246    bool ret = false;
6247    // 引数チェック
6248    if (h == NULL || ticket == NULL || username == NULL || usernamereal == NULL || policy == NULL || sessionname == NULL)
6249    {
6250        return false;
6251    }
6252
6253    LockList(h->TicketList);
6254    {
6255        UINT i;
6256        for (i = 0;i < LIST_NUM(h->TicketList);i++)
6257        {
6258            TICKET *t = LIST_DATA(h->TicketList, i);
6259            if (Cmp(t->Ticket, ticket, SHA1_SIZE) == 0)
6260            {
6261                ret = true;
6262                StrCpy(username, username_size, t->Username);
6263                StrCpy(usernamereal, usernamereal_size, t->UsernameReal);
6264                StrCpy(sessionname, sessionname_size, t->SessionName);
6265                StrCpy(groupname, groupname_size, t->GroupName);
6266                Copy(policy, &t->Policy, sizeof(POLICY));
6267                Delete(h->TicketList, t);
6268                Free(t);
6269                break;
6270            }
6271        }
6272    }
6273    UnlockList(h->TicketList);
6274
6275    return ret;
6276}
6277
6278// MAC アドレス削除指令受信
6279void SiCalledDeleteMacTable(SERVER *s, PACK *p)
6280{
6281    UINT key;
6282    char hubname[MAX_HUBNAME_LEN + 1];
6283    HUB *h;
6284    // 引数チェック
6285    if (s == NULL || p == NULL)
6286    {
6287        return;
6288    }
6289
6290    if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
6291    {
6292        return;
6293    }
6294    key = PackGetInt(p, "Key");
6295
6296    LockHubList(s->Cedar);
6297    {
6298        h = GetHub(s->Cedar, hubname);
6299    }
6300    UnlockHubList(s->Cedar);
6301
6302    if (h == NULL)
6303    {
6304        return;
6305    }
6306
6307    LockList(h->MacTable);
6308    {
6309        if (IsInList(h->MacTable, (void *)key))
6310        {
6311            MAC_TABLE_ENTRY *e = (MAC_TABLE_ENTRY *)key;
6312            Delete(h->MacTable, e);
6313            Free(e);
6314        }
6315    }
6316    UnlockList(h->MacTable);
6317
6318    ReleaseHub(h);
6319}
6320
6321// IP アドレス削除指令受信
6322void SiCalledDeleteIpTable(SERVER *s, PACK *p)
6323{
6324    UINT key;
6325    char hubname[MAX_HUBNAME_LEN + 1];
6326    HUB *h;
6327    // 引数チェック
6328    if (s == NULL || p == NULL)
6329    {
6330        return;
6331    }
6332
6333    if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
6334    {
6335        return;
6336    }
6337    key = PackGetInt(p, "Key");
6338
6339    LockHubList(s->Cedar);
6340    {
6341        h = GetHub(s->Cedar, hubname);
6342    }
6343    UnlockHubList(s->Cedar);
6344
6345    if (h == NULL)
6346    {
6347        return;
6348    }
6349
6350    LockList(h->IpTable);
6351    {
6352        if (IsInList(h->IpTable, (void *)key))
6353        {
6354            IP_TABLE_ENTRY *e = (IP_TABLE_ENTRY *)key;
6355            Delete(h->IpTable, e);
6356            Free(e);
6357        }
6358    }
6359    UnlockList(h->IpTable);
6360
6361    ReleaseHub(h);
6362}
6363
6364// セッション削除指令受信
6365void SiCalledDeleteSession(SERVER *s, PACK *p)
6366{
6367    char name[MAX_SESSION_NAME_LEN + 1];
6368    char hubname[MAX_HUBNAME_LEN + 1];
6369    HUB *h;
6370    SESSION *sess;
6371    // 引数チェック
6372    if (s == NULL || p == NULL)
6373    {
6374        return;
6375    }
6376
6377    if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
6378    {
6379        return;
6380    }
6381    if (PackGetStr(p, "SessionName", name, sizeof(name)) == false)
6382    {
6383        return;
6384    }
6385
6386    LockHubList(s->Cedar);
6387    {
6388        h = GetHub(s->Cedar, hubname);
6389    }
6390    UnlockHubList(s->Cedar);
6391
6392    if (h == NULL)
6393    {
6394        return;
6395    }
6396
6397    sess = GetSessionByName(h, name);
6398
6399    if (sess != NULL)
6400    {
6401        if (sess->BridgeMode == false && sess->LinkModeServer == false && sess->SecureNATMode == false)
6402        {
6403            StopSession(sess);
6404        }
6405        ReleaseSession(sess);
6406    }
6407
6408    ReleaseHub(h);
6409}
6410
6411// ログファイル読み込み指令受信
6412PACK *SiCalledReadLogFile(SERVER *s, PACK *p)
6413{
6414    RPC_READ_LOG_FILE t;
6415    PACK *ret;
6416    char filepath[MAX_PATH];
6417    UINT offset;
6418    // 引数チェック
6419    if (s == NULL || p == NULL)
6420    {
6421        return NULL;
6422    }
6423
6424    PackGetStr(p, "FilePath", filepath, sizeof(filepath));
6425    offset = PackGetInt(p, "Offset");
6426
6427    Zero(&t, sizeof(t));
6428
6429    SiReadLocalLogFile(s, filepath, offset, &t);
6430
6431    ret = NewPack();
6432
6433    OutRpcReadLogFile(ret, &t);
6434    FreeRpcReadLogFile(&t);
6435
6436    return ret;
6437}
6438
6439// ログファイル列挙指令受信
6440PACK *SiCalledEnumLogFileList(SERVER *s, PACK *p)
6441{
6442    RPC_ENUM_LOG_FILE t;
6443    PACK *ret;
6444    char hubname[MAX_HUBNAME_LEN + 1];
6445    // 引数チェック
6446    if (s == NULL || p == NULL)
6447    {
6448        return NULL;
6449    }
6450
6451    PackGetStr(p, "HubName", hubname, sizeof(hubname));
6452
6453    Zero(&t, sizeof(t));
6454
6455    SiEnumLocalLogFileList(s, hubname, &t);
6456
6457    ret = NewPack();
6458
6459    OutRpcEnumLogFile(ret, &t);
6460    FreeRpcEnumLogFile(&t);
6461
6462    return ret;
6463}
6464
6465// セッション情報指令受信
6466PACK *SiCalledGetSessionStatus(SERVER *s, PACK *p)
6467{
6468    RPC_SESSION_STATUS t;
6469    ADMIN a;
6470    PACK *ret;
6471    // 引数チェック
6472    if (s == NULL || p == NULL)
6473    {
6474        return NULL;
6475    }
6476
6477    Zero(&t, sizeof(t));
6478    InRpcSessionStatus(&t, p);
6479
6480    Zero(&a, sizeof(a));
6481    a.Server = s;
6482    a.ServerAdmin = true;
6483
6484    if (StGetSessionStatus(&a, &t) != ERR_NO_ERROR)
6485    {
6486        FreeRpcSessionStatus(&t);
6487        return NULL;
6488    }
6489
6490    ret = NewPack();
6491
6492    OutRpcSessionStatus(ret, &t);
6493
6494    FreeRpcSessionStatus(&t);
6495
6496    return ret;
6497}
6498
6499// IP テーブル列挙指令
6500PACK *SiCalledEnumIpTable(SERVER *s, PACK *p)
6501{
6502    char hubname[MAX_HUBNAME_LEN + 1];
6503    RPC_ENUM_IP_TABLE t;
6504    PACK *ret;
6505    // 引数チェック
6506    if (s == NULL || p == NULL)
6507    {
6508        return NewPack();
6509    }
6510    if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
6511    {
6512        return NewPack();
6513    }
6514    Zero(&t, sizeof(t));
6515
6516    SiEnumIpTable(s, hubname, &t);
6517
6518    ret = NewPack();
6519    OutRpcEnumIpTable(ret, &t);
6520    FreeRpcEnumIpTable(&t);
6521
6522    return ret;
6523}
6524
6525// MAC テーブル列挙指令
6526PACK *SiCalledEnumMacTable(SERVER *s, PACK *p)
6527{
6528    char hubname[MAX_HUBNAME_LEN + 1];
6529    RPC_ENUM_MAC_TABLE t;
6530    PACK *ret;
6531    // 引数チェック
6532    if (s == NULL || p == NULL)
6533    {
6534        return NewPack();
6535    }
6536    if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
6537    {
6538        return NewPack();
6539    }
6540    Zero(&t, sizeof(t));
6541
6542    SiEnumMacTable(s, hubname, &t);
6543
6544    ret = NewPack();
6545    OutRpcEnumMacTable(ret, &t);
6546    FreeRpcEnumMacTable(&t);
6547
6548    return ret;
6549}
6550
6551// NAT の状況取得指令
6552PACK *SiCalledGetNatStatus(SERVER *s, PACK *p)
6553{
6554    char hubname[MAX_HUBNAME_LEN + 1];
6555    RPC_NAT_STATUS t;
6556    PACK *ret;
6557    HUB *h;
6558    // 引数チェック
6559    if (s == NULL || p == NULL)
6560    {
6561        return NewPack();
6562    }
6563    if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
6564    {
6565        return NewPack();
6566    }
6567    Zero(&t, sizeof(t));
6568
6569    LockHubList(s->Cedar);
6570    {
6571        h = GetHub(s->Cedar, hubname);
6572    }
6573    UnlockHubList(s->Cedar);
6574
6575    if (h != NULL)
6576    {
6577        Lock(h->lock_online);
6578        {
6579            if (h->SecureNAT != NULL)
6580            {
6581                NtGetStatus(h->SecureNAT->Nat, &t);
6582            }
6583        }
6584        Unlock(h->lock_online);
6585    }
6586
6587    ReleaseHub(h);
6588
6589    ret = NewPack();
6590    OutRpcNatStatus(ret, &t);
6591    FreeRpcNatStatus(&t);
6592
6593    return ret;
6594}
6595
6596// DHCP テーブル列挙指令
6597PACK *SiCalledEnumDhcp(SERVER *s, PACK *p)
6598{
6599    char hubname[MAX_HUBNAME_LEN + 1];
6600    RPC_ENUM_DHCP t;
6601    PACK *ret;
6602    HUB *h;
6603    // 引数チェック
6604    if (s == NULL || p == NULL)
6605    {
6606        return NewPack();
6607    }
6608    if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
6609    {
6610        return NewPack();
6611    }
6612    Zero(&t, sizeof(t));
6613
6614    LockHubList(s->Cedar);
6615    {
6616        h = GetHub(s->Cedar, hubname);
6617    }
6618    UnlockHubList(s->Cedar);
6619
6620    if (h != NULL)
6621    {
6622        Lock(h->lock_online);
6623        {
6624            if (h->SecureNAT != NULL)
6625            {
6626                NtEnumDhcpList(h->SecureNAT->Nat, &t);
6627            }
6628        }
6629        Unlock(h->lock_online);
6630    }
6631
6632    ReleaseHub(h);
6633
6634    ret = NewPack();
6635    OutRpcEnumDhcp(ret, &t);
6636    FreeRpcEnumDhcp(&t);
6637
6638    return ret;
6639}
6640
6641// NAT テーブル列挙指令
6642PACK *SiCalledEnumNat(SERVER *s, PACK *p)
6643{
6644    char hubname[MAX_HUBNAME_LEN + 1];
6645    RPC_ENUM_NAT t;
6646    PACK *ret;
6647    HUB *h;
6648    // 引数チェック
6649    if (s == NULL || p == NULL)
6650    {
6651        return NewPack();
6652    }
6653    if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
6654    {
6655        return NewPack();
6656    }
6657    Zero(&t, sizeof(t));
6658
6659    LockHubList(s->Cedar);
6660    {
6661        h = GetHub(s->Cedar, hubname);
6662    }
6663    UnlockHubList(s->Cedar);
6664
6665    if (h != NULL)
6666    {
6667        Lock(h->lock_online);
6668        {
6669            if (h->SecureNAT != NULL)
6670            {
6671                NtEnumNatList(h->SecureNAT->Nat, &t);
6672            }
6673        }
6674        Unlock(h->lock_online);
6675    }
6676
6677    ReleaseHub(h);
6678
6679    ret = NewPack();
6680    OutRpcEnumNat(ret, &t);
6681    FreeRpcEnumNat(&t);
6682
6683    return ret;
6684}
6685
6686// セッション列挙指令受信
6687PACK *SiCalledEnumSession(SERVER *s, PACK *p)
6688{
6689    char hubname[MAX_HUBNAME_LEN + 1];
6690    RPC_ENUM_SESSION t;
6691    PACK *ret;
6692    // 引数チェック
6693    if (s == NULL || p == NULL)
6694    {
6695        return NewPack();
6696    }
6697    if (PackGetStr(p, "HubName", hubname, sizeof(hubname)) == false)
6698    {
6699        return NewPack();
6700    }
6701    Zero(&t, sizeof(t));
6702
6703    SiEnumLocalSession(s, hubname, &t);
6704
6705    ret = NewPack();
6706    OutRpcEnumSession(ret, &t);
6707    FreeRpcEnumSession(&t);
6708
6709    return ret;
6710}
6711
6712// チケット作成指令受信
6713PACK *SiCalledCreateTicket(SERVER *s, PACK *p)
6714{
6715    char username[MAX_SIZE];
6716    char hubname[MAX_SIZE];
6717    char groupname[MAX_SIZE];
6718    char realusername[MAX_SIZE];
6719    char sessionname[MAX_SESSION_NAME_LEN + 1];
6720    POLICY policy;
6721    UCHAR ticket[SHA1_SIZE];
6722    char ticket_str[MAX_SIZE];
6723    HUB *h;
6724    UINT i;
6725    PACK *ret;
6726    TICKET *t;
6727    // 引数チェック
6728    if (s == NULL || p == NULL)
6729    {
6730        return NewPack();
6731    }
6732
6733    PackGetStr(p, "UserName", username, sizeof(username));
6734    PackGetStr(p, "GroupName", groupname, sizeof(groupname));
6735    PackGetStr(p, "HubName", hubname, sizeof(hubname));
6736    PackGetStr(p, "RealUserName", realusername, sizeof(realusername));
6737    PackGetStr(p, "SessionName", sessionname, sizeof(sessionname));
6738
6739    InRpcPolicy(&policy, p);
6740    if (PackGetDataSize(p, "Ticket") == SHA1_SIZE)
6741    {
6742        PackGetData(p, "Ticket", ticket);
6743    }
6744
6745    BinToStr(ticket_str, sizeof(ticket_str), ticket, SHA1_SIZE);
6746
6747    SLog(s->Cedar, "LS_TICKET_2", hubname, username, realusername, sessionname,
6748        ticket_str, TICKET_EXPIRES / 1000);
6749
6750    // HUB を取得
6751    h = GetHub(s->Cedar, hubname);
6752    if (h == NULL)
6753    {
6754        return NewPack();
6755    }
6756
6757    LockList(h->TicketList);
6758    {
6759        LIST *o = NewListFast(NULL);
6760        // 古いチケットを破棄
6761        for (i = 0;i < LIST_NUM(h->TicketList);i++)
6762        {
6763            TICKET *t = LIST_DATA(h->TicketList, i);
6764            if ((t->CreatedTick + TICKET_EXPIRES) < Tick64())
6765            {
6766                Add(o, t);
6767            }
6768        }
6769        for (i = 0;i < LIST_NUM(o);i++)
6770        {
6771            TICKET *t = LIST_DATA(o, i);
6772            Delete(h->TicketList, t);
6773            Free(t);
6774        }
6775        ReleaseList(o);
6776
6777        // チケットを作成
6778        t = ZeroMalloc(sizeof(TICKET));
6779        t->CreatedTick = Tick64();
6780        Copy(&t->Policy, &policy, sizeof(POLICY));
6781        Copy(t->Ticket, ticket, SHA1_SIZE);
6782        StrCpy(t->Username, sizeof(t->Username), username);
6783        StrCpy(t->UsernameReal, sizeof(t->UsernameReal), realusername);
6784        StrCpy(t->GroupName, sizeof(t->GroupName), groupname);
6785        StrCpy(t->SessionName, sizeof(t->SessionName), sessionname);
6786
6787        Add(h->TicketList, t);
6788    }
6789    UnlockList(h->TicketList);
6790
6791    ReleaseHub(h);
6792
6793    ret = NewPack();
6794
6795    PackAddInt(ret, "Point", SiGetPoint(s));
6796
6797    return ret;
6798}
6799
6800// HUB 作成指令受信
6801void SiCalledCreateHub(SERVER *s, PACK *p)
6802{
6803    char name[MAX_SIZE];
6804    UINT type;
6805    HUB_OPTION o;
6806    HUB_LOG log;
6807    bool save_packet_log;
6808    UINT packet_log_switch_type;
6809    UINT packet_log_config[NUM_PACKET_LOG];
6810    bool save_security_log;
6811    UINT security_log_switch_type;
6812    UINT i;
6813    HUB *h;
6814    // 引数チェック
6815    if (s == NULL || p == NULL)
6816    {
6817        return;
6818    }
6819
6820    PackGetStr(p, "HubName", name, sizeof(name));
6821    type = PackGetInt(p, "HubType");
6822    Zero(&o, sizeof(o));
6823    o.MaxSession = PackGetInt(p, "MaxSession");
6824    save_packet_log = PackGetInt(p, "SavePacketLog");
6825    packet_log_switch_type = PackGetInt(p, "PacketLogSwitchType");
6826    for (i = 0;i < NUM_PACKET_LOG;i++)
6827    {
6828        packet_log_config[i] = PackGetIntEx(p, "PacketLogConfig", i);
6829    }
6830    save_security_log = PackGetInt(p, "SaveSecurityLog");
6831    security_log_switch_type = PackGetInt(p, "SecurityLogSwitchType");
6832
6833    Zero(&log, sizeof(log));
6834    log.SavePacketLog = save_packet_log;
6835    log.PacketLogSwitchType = packet_log_switch_type;
6836    Copy(log.PacketLogConfig, packet_log_config, sizeof(log.PacketLogConfig));
6837    log.SaveSecurityLog = save_security_log;
6838    log.SecurityLogSwitchType = security_log_switch_type;
6839
6840    h = NewHub(s->Cedar, name, &o);
6841    h->LastCommTime = h->LastLoginTime = h->CreatedTime = 0;
6842    SetHubLogSetting(h, &log);
6843    h->Type = type;
6844    h->FarmMember_MaxSessionClient = PackGetInt(p, "MaxSessionClient");
6845    h->FarmMember_MaxSessionBridge = PackGetInt(p, "MaxSessionBridge");
6846    h->FarmMember_MaxSessionClientBridgeApply = PackGetBool(p, "MaxSessionClientBridgeApply");
6847
6848    if (h->FarmMember_MaxSessionClientBridgeApply == false)
6849    {
6850        h->FarmMember_MaxSessionClient = INFINITE;
6851        h->FarmMember_MaxSessionBridge = INFINITE;
6852    }
6853
6854    PackGetData2(p, "SecurePassword", h->SecurePassword, SHA1_SIZE);
6855    PackGetData2(p, "HashedPassword", h->HashedPassword, SHA1_SIZE);
6856
6857    for (i = 0;i < SiNumAccessFromPack(p);i++)
6858    {
6859        ACCESS *a = SiPackToAccess(p, i);
6860        AddAccessList(h, a);
6861        Free(a);
6862    }
6863
6864    if (PackGetBool(p, "EnableSecureNAT"))
6865    {
6866        VH_OPTION t;
6867
6868        InVhOption(&t, p);
6869
6870        Copy(h->SecureNATOption, &t, sizeof(VH_OPTION));
6871        EnableSecureNAT(h, true);
6872
6873        Debug("SiCalledCreateHub: SecureNAT Created.\n");
6874    }
6875
6876    AddHub(s->Cedar, h);
6877    h->Offline = true;
6878    SetHubOnline(h);
6879
6880    ReleaseHub(h);
6881}
6882
6883// ファームコントロールスレッド
6884void SiFarmControlThread(THREAD *thread, void *param)
6885{
6886    SERVER *s;
6887    CEDAR *c;
6888    EVENT *e;
6889    LIST *o;
6890    UINT i;
6891    char tmp[MAX_PATH];
6892    // 引数チェック
6893    if (thread == NULL || param == NULL)
6894    {
6895        return;
6896    }
6897
6898    s = (SERVER *)param;
6899    c = s->Cedar;
6900    e = s->FarmControlThreadHaltEvent;
6901
6902    while (true)
6903    {
6904        Lock(c->CedarSuperLock);
6905
6906        // 各ファームメンバーがホストしている HUB 一覧を列挙する
6907        Format(tmp, sizeof(tmp), "CONTROLLER: %s %u", __FILE__, __LINE__);
6908        SiDebugLog(s, tmp);
6909
6910        LockList(s->FarmMemberList);
6911        {
6912            UINT i;
6913            UINT num;
6914            UINT assigned_client_license = 0;
6915            UINT assigned_bridge_license = 0;
6916
6917            Format(tmp, sizeof(tmp), "CONTROLLER: %s %u", __FILE__, __LINE__);
6918            SiDebugLog(s, tmp);
6919
6920            num = 0;
6921
6922            for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
6923            {
6924                FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
6925                SiCallEnumHub(s, f);
6926                // サーバーファーム全体での合計セッション数を取得する
6927                num += f->NumSessions;
6928
6929                assigned_client_license += f->AssignedClientLicense;
6930                assigned_bridge_license += f->AssignedBridgeLicense;
6931            }
6932
6933            s->CurrentTotalNumSessionsOnFarm = num;
6934
6935            // 割り当て済みライセンス数を更新する
6936            s->CurrentAssignedBridgeLicense = assigned_bridge_license;
6937            s->CurrentAssignedClientLicense = assigned_client_license;
6938
6939            Format(tmp, sizeof(tmp), "CONTROLLER: %s %u", __FILE__, __LINE__);
6940            SiDebugLog(s, tmp);
6941        }
6942        UnlockList(s->FarmMemberList);
6943
6944        Format(tmp, sizeof(tmp), "CONTROLLER: %s %u", __FILE__, __LINE__);
6945        SiDebugLog(s, tmp);
6946
6947        o = NewListFast(NULL);
6948
6949        Format(tmp, sizeof(tmp), "CONTROLLER: %s %u", __FILE__, __LINE__);
6950        SiDebugLog(s, tmp);
6951
6952        // 各 HUB に対して更新通知を発する
6953        LockList(c->HubList);
6954        {
6955            UINT i;
6956            for (i = 0;i < LIST_NUM(c->HubList);i++)
6957            {
6958                HUB *h = LIST_DATA(c->HubList, i);
6959                AddRef(h->ref);
6960                Add(o, h);
6961            }
6962        }
6963        UnlockList(c->HubList);
6964
6965        Format(tmp, sizeof(tmp), "CONTROLLER: %s %u", __FILE__, __LINE__);
6966        SiDebugLog(s, tmp);
6967
6968        for (i = 0;i < LIST_NUM(o);i++)
6969        {
6970            HUB *h = LIST_DATA(o, i);
6971            SiHubUpdateProc(h);
6972            ReleaseHub(h);
6973        }
6974
6975        Format(tmp, sizeof(tmp), "CONTROLLER: %s %u", __FILE__, __LINE__);
6976        SiDebugLog(s, tmp);
6977
6978        ReleaseList(o);
6979
6980        Unlock(c->CedarSuperLock);
6981
6982        Wait(e, SERVER_FARM_CONTROL_INTERVAL);
6983        if (s->Halt)
6984        {
6985            break;
6986        }
6987    }
6988}
6989
6990// ファームコントロールの開始
6991void SiStartFarmControl(SERVER *s)
6992{
6993    // 引数チェック
6994    if (s == NULL || s->ServerType != SERVER_TYPE_FARM_CONTROLLER)
6995    {
6996        return;
6997    }
6998
6999    s->FarmControlThreadHaltEvent = NewEvent();
7000    s->FarmControlThread = NewThread(SiFarmControlThread, s);
7001}
7002
7003// ファームコントロールの終了
7004void SiStopFarmControl(SERVER *s)
7005{
7006    // 引数チェック
7007    if (s == NULL || s->ServerType != SERVER_TYPE_FARM_CONTROLLER)
7008    {
7009        return;
7010    }
7011
7012    Set(s->FarmControlThreadHaltEvent);
7013    WaitThread(s->FarmControlThread, INFINITE);
7014    ReleaseEvent(s->FarmControlThreadHaltEvent);
7015    ReleaseThread(s->FarmControlThread);
7016}
7017
7018// HUB 列挙指令
7019void SiCallEnumHub(SERVER *s, FARM_MEMBER *f)
7020{
7021    CEDAR *c;
7022    // 引数チェック
7023    if (s == NULL || f == NULL)
7024    {
7025        return;
7026    }
7027
7028    c = s->Cedar;
7029
7030    if (f->Me)
7031    {
7032        LICENSE_STATUS st;
7033
7034        LiParseCurrentLicenseStatus(s->LicenseSystem, &st);
7035
7036        // ローカルの HUB を列挙する
7037        LockList(f->HubList);
7038        {
7039            // ローカル HUB の場合、まず STATIC HUB リストを一旦
7040            // すべて消去して再列挙を行うようにする
7041            UINT i;
7042            LIST *o = NewListFast(NULL);
7043            for (i = 0;i < LIST_NUM(f->HubList);i++)
7044            {
7045                HUB_LIST *h = LIST_DATA(f->HubList, i);
7046                if (h->DynamicHub == false)
7047                {
7048                    Add(o, h);
7049                }
7050            }
7051
7052            // STATIC HUB をすべて消去
7053            for (i = 0;i < LIST_NUM(o);i++)
7054            {
7055                HUB_LIST *h = LIST_DATA(o, i);
7056                Free(h);
7057                Delete(f->HubList, h);
7058            }
7059            ReleaseList(o);
7060
7061            // 次に DYNAMIC HUB でユーザーが 1 人もいないものを停止する
7062            o = NewListFast(NULL);
7063            for (i = 0;i < LIST_NUM(f->HubList);i++)
7064            {
7065                HUB_LIST *h = LIST_DATA(f->HubList, i);
7066                if (h->DynamicHub == true)
7067                {
7068                    LockList(c->HubList);
7069                    {
7070                        HUB *hub = GetHub(s->Cedar, h->Name);
7071                        if (hub != NULL)
7072                        {
7073                            if (Count(hub->NumSessions) == 0 || hub->Type != HUB_TYPE_FARM_DYNAMIC)
7074                            {
7075                                Add(o, h);
7076                            }
7077                            ReleaseHub(hub);
7078                        }
7079                    }
7080                    UnlockList(c->HubList);
7081                }
7082            }
7083
7084            for (i = 0;i < LIST_NUM(o);i++)
7085            {
7086                HUB_LIST *h = LIST_DATA(o, i);
7087                Debug("Delete HUB: %s\n", h->Name);
7088                Free(h);
7089                Delete(f->HubList, h);
7090            }
7091
7092            ReleaseList(o);
7093
7094            // 列挙結果を設定
7095            LockList(c->HubList);
7096            {
7097                for (i = 0;i < LIST_NUM(c->HubList);i++)
7098                {
7099                    HUB *h = LIST_DATA(c->HubList, i);
7100                    if (h->Offline == false)
7101                    {
7102                        if (h->Type == HUB_TYPE_FARM_STATIC)
7103                        {
7104                            HUB_LIST *hh = ZeroMalloc(sizeof(HUB_LIST));
7105                            hh->FarmMember = f;
7106                            hh->DynamicHub = false;
7107                            StrCpy(hh->Name, sizeof(hh->Name), h->Name);
7108                            Add(f->HubList, hh);
7109
7110                            LockList(h->SessionList);
7111                            {
7112                                hh->NumSessions = LIST_NUM(h->SessionList);
7113                                hh->NumSessionsBridge = Count(h->NumSessionsBridge);
7114                                hh->NumSessionsClient = Count(h->NumSessionsClient);
7115                            }
7116                            UnlockList(h->SessionList);
7117
7118                            LockList(h->MacTable);
7119                            {
7120                                hh->NumMacTables = LIST_NUM(h->MacTable);
7121                            }
7122                            UnlockList(h->MacTable);
7123
7124                            LockList(h->IpTable);
7125                            {
7126                                hh->NumIpTables = LIST_NUM(h->IpTable);
7127                            }
7128                            UnlockList(h->IpTable);
7129                        }
7130                    }
7131                }
7132            }
7133            UnlockList(c->HubList);
7134        }
7135        UnlockList(f->HubList);
7136
7137        // ポイント
7138        f->Point = SiGetPoint(s);
7139        f->NumSessions = Count(s->Cedar->CurrentSessions);
7140        f->MaxSessions = GetServerCapsInt(s, "i_max_sessions");
7141        f->NumTcpConnections = Count(s->Cedar->CurrentTcpConnections);
7142
7143        Lock(s->Cedar->TrafficLock);
7144        {
7145            Copy(&f->Traffic, s->Cedar->Traffic, sizeof(TRAFFIC));
7146        }
7147        Unlock(s->Cedar->TrafficLock);
7148
7149        f->AssignedBridgeLicense = Count(s->Cedar->AssignedBridgeLicense);
7150        f->AssignedClientLicense = Count(s->Cedar->AssignedClientLicense);
7151
7152        Copy(f->RandomKey, s->MyRandomKey, SHA1_SIZE);
7153        f->SystemId = st.SystemId;
7154
7155        Debug("Server %s: Point %u\n", f->hostname, f->Point);
7156    }
7157    else
7158    {
7159        // リモートのメンバの HUB を列挙する
7160        PACK *p = NewPack();
7161        UINT i, num, j;
7162        LIST *o = NewListFast(NULL);
7163
7164        num = 0;
7165
7166        for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
7167        {
7168            FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
7169
7170            if (IsZero(f->RandomKey, SHA1_SIZE) == false && f->SystemId != 0)
7171            {
7172                num++;
7173            }
7174        }
7175
7176        j = 0;
7177
7178        for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
7179        {
7180            FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
7181
7182            if (IsZero(f->RandomKey, SHA1_SIZE) == false && f->SystemId != 0)
7183            {
7184                PackAddDataEx(p, "MemberRandomKey", f->RandomKey, SHA1_SIZE, j, num);
7185                PackAddInt64Ex(p, "MemberSystemId", f->SystemId, j, num);
7186                j++;
7187            }
7188        }
7189        PackAddInt(p, "MemberSystemIdNum", num);
7190
7191        p = SiCallTask(f, p, "enumhub");
7192        if (p != NULL)
7193        {
7194            LockList(f->HubList);
7195            {
7196                UINT i;
7197                // リスト消去
7198                for (i = 0;i < LIST_NUM(f->HubList);i++)
7199                {
7200                    HUB_LIST *hh = LIST_DATA(f->HubList, i);
7201                    Free(hh);
7202                }
7203                DeleteAll(f->HubList);
7204
7205                for (i = 0;i < PackGetIndexCount(p, "HubName");i++)
7206                {
7207                    HUB_LIST *hh = ZeroMalloc(sizeof(HUB_LIST));
7208                    UINT num;
7209                    UINT64 LastCommTime;
7210
7211                    PackGetStrEx(p, "HubName", hh->Name, sizeof(hh->Name), i);
7212                    num = PackGetIntEx(p, "NumSession", i);
7213                    hh->DynamicHub = ((PackGetIntEx(p, "HubType", i) == HUB_TYPE_FARM_DYNAMIC) ? true : false);
7214                    hh->FarmMember = f;
7215                    hh->NumSessions = PackGetIntEx(p, "NumSessions", i);
7216                    hh->NumSessionsClient = PackGetIntEx(p, "NumSessionsClient", i);
7217                    hh->NumSessionsBridge = PackGetIntEx(p, "NumSessionsBridge", i);
7218                    hh->NumIpTables = PackGetIntEx(p, "NumIpTables", i);
7219                    hh->NumMacTables = PackGetIntEx(p, "NumMacTables", i);
7220                    LastCommTime = PackGetInt64Ex(p, "LastCommTime", i);
7221                    Add(f->HubList, hh);
7222                    Debug("%s\n", hh->Name);
7223
7224                    LockList(c->HubList);
7225                    {
7226                        HUB *h = GetHub(c, hh->Name);
7227
7228                        if (h != NULL)
7229                        {
7230                            // 仮想 HUB の LastCommTime を更新する
7231                            Lock(h->lock);
7232                            {
7233                                if (h->LastCommTime < LastCommTime)
7234                                {
7235                                    h->LastCommTime = LastCommTime;
7236                                }
7237                            }
7238                            Unlock(h->lock);
7239
7240                            ReleaseHub(h);
7241                        }
7242                    }
7243                    UnlockList(c->HubList);
7244
7245                    if (hh->DynamicHub && num >= 1)
7246                    {
7247                        // すでにユーザーセッションが 1 以上接続されているので
7248                        // 仮想 HUB 作成履歴リストに登録しておく必要はない
7249                        // 仮想 HUB 作成履歴リストから削除する
7250                        SiDelHubCreateHistory(s, hh->Name);
7251                    }
7252
7253                    if (hh->DynamicHub && num == 0)
7254                    {
7255                        // 仮想 HUB 作成履歴リストを確認する
7256                        // 直近 60 秒以内に作成され、まだ 1 人目のユーザーが接続
7257                        // していない仮想 HUB の場合は、ユーザーが 1 人もいないという
7258                        // 理由で削除しない
7259                        if (SiIsHubRegistedOnCreateHistory(s, hh->Name) == false)
7260                        {
7261                            // ダイナミック HUB でユーザーが 1 人もいないので停止する
7262                            HUB *h;
7263                            LockList(c->HubList);
7264                            {
7265                                h = GetHub(c, hh->Name);
7266                            }
7267                            UnlockList(c->HubList);
7268
7269                            if (h != NULL)
7270                            {
7271                                Add(o, h);
7272                            }
7273                        }
7274                    }
7275                }
7276            }
7277            UnlockList(f->HubList);
7278            f->Point = PackGetInt(p, "Point");
7279            Debug("Server %s: Point %u\n", f->hostname, f->Point);
7280            f->NumSessions = PackGetInt(p, "NumTotalSessions");
7281            if (f->NumSessions == 0)
7282            {
7283                f->NumSessions = PackGetInt(p, "NumSessions");
7284            }
7285            f->MaxSessions = PackGetInt(p, "MaxSessions");
7286            f->NumTcpConnections = PackGetInt(p, "NumTcpConnections");
7287            InRpcTraffic(&f->Traffic, p);
7288
7289            f->AssignedBridgeLicense = PackGetInt(p, "AssignedBridgeLicense");
7290            f->AssignedClientLicense = PackGetInt(p, "AssignedClientLicense");
7291
7292            if (PackGetDataSize(p, "RandomKey") == SHA1_SIZE)
7293            {
7294                PackGetData(p, "RandomKey", f->RandomKey);
7295            }
7296
7297            f->SystemId = PackGetInt64(p, "SystemId");
7298
7299            // トラフィック差分情報を適用する
7300            num = PackGetIndexCount(p, "TdType");
7301            for (i = 0;i < num;i++)
7302            {
7303                TRAFFIC traffic;
7304                UINT type;
7305                HUB *h;
7306                char name[MAX_SIZE];
7307                char hubname[MAX_SIZE];
7308
7309                type = PackGetIntEx(p, "TdType", i);
7310                PackGetStrEx(p, "TdName", name, sizeof(name), i);
7311                PackGetStrEx(p, "TdHubName", hubname, sizeof(hubname), i);
7312                InRpcTrafficEx(&traffic, p, i);
7313
7314                LockList(c->HubList);
7315                {
7316                    h = GetHub(c, hubname);
7317                    if (h != NULL)
7318                    {
7319                        if (type == TRAFFIC_DIFF_HUB)
7320                        {
7321                            Lock(h->TrafficLock);
7322                            {
7323                                AddTraffic(h->Traffic, &traffic);
7324                            }
7325                            Unlock(h->TrafficLock);
7326                        }
7327                        else
7328                        {
7329                            AcLock(h);
7330                            {
7331                                USER *u = AcGetUser(h, name);
7332                                if (u != NULL)
7333                                {
7334                                    Lock(u->lock);
7335                                    {
7336                                        AddTraffic(u->Traffic, &traffic);
7337                                    }
7338                                    Unlock(u->lock);
7339                                    if (u->Group != NULL)
7340                                    {
7341                                        Lock(u->Group->lock);
7342                                        {
7343                                            AddTraffic(u->Group->Traffic, &traffic);
7344                                        }
7345                                        Unlock(u->Group->lock);
7346                                    }
7347                                    ReleaseUser(u);
7348                                }
7349                            }
7350                            AcUnlock(h);
7351                        }
7352                        ReleaseHub(h);
7353                    }
7354                    UnlockList(c->HubList);
7355                }
7356            }
7357
7358            FreePack(p);
7359        }
7360
7361        for (i = 0;i < LIST_NUM(o);i++)
7362        {
7363            HUB *h = LIST_DATA(o, i);
7364            SiCallDeleteHub(s, f, h);
7365            Debug("Delete HUB: %s\n", h->Name);
7366            ReleaseHub(h);
7367        }
7368
7369        ReleaseList(o);
7370    }
7371}
7372
7373// セッション情報取得指令
7374bool SiCallGetSessionStatus(SERVER *s, FARM_MEMBER *f, RPC_SESSION_STATUS *t)
7375{
7376    PACK *p;
7377    // 引数チェック
7378    if (s == NULL || f == NULL)
7379    {
7380        return false;
7381    }
7382
7383    p = NewPack();
7384    OutRpcSessionStatus(p, t);
7385    FreeRpcSessionStatus(t);
7386    Zero(t, sizeof(RPC_SESSION_STATUS));
7387
7388    p = SiCallTask(f, p, "getsessionstatus");
7389
7390    if (p == NULL)
7391    {
7392        return false;
7393    }
7394
7395    InRpcSessionStatus(t, p);
7396    FreePack(p);
7397
7398    return true;
7399}
7400
7401// ログファイル読み込み指令
7402bool SiCallReadLogFile(SERVER *s, FARM_MEMBER *f, RPC_READ_LOG_FILE *t)
7403{
7404    PACK *p;
7405    // 引数チェック
7406    if (s == NULL || f == NULL)
7407    {
7408        return false;
7409    }
7410
7411    p = NewPack();
7412    OutRpcReadLogFile(p, t);
7413    FreeRpcReadLogFile(t);
7414    Zero(t, sizeof(RPC_READ_LOG_FILE));
7415
7416    p = SiCallTask(f, p, "readlogfile");
7417
7418    if (p == NULL)
7419    {
7420        return false;
7421    }
7422
7423    InRpcReadLogFile(t, p);
7424    FreePack(p);
7425
7426    return true;
7427}
7428
7429// ログファイルリスト列挙指令
7430bool SiCallEnumLogFileList(SERVER *s, FARM_MEMBER *f, RPC_ENUM_LOG_FILE *t, char *hubname)
7431{
7432    PACK *p;
7433    // 引数チェック
7434    if (s == NULL || f == NULL)
7435    {
7436        return false;
7437    }
7438
7439    p = NewPack();
7440    OutRpcEnumLogFile(p, t);
7441    FreeRpcEnumLogFile(t);
7442    Zero(t, sizeof(RPC_ENUM_LOG_FILE));
7443
7444    PackAddStr(p, "HubName", hubname);
7445
7446    p = SiCallTask(f, p, "enumlogfilelist");
7447
7448    if (p == NULL)
7449    {
7450        return false;
7451    }
7452
7453    InRpcEnumLogFile(t, p);
7454    FreePack(p);
7455
7456    return true;
7457}
7458
7459// HUB 削除指令
7460void SiCallDeleteHub(SERVER *s, FARM_MEMBER *f, HUB *h)
7461{
7462    PACK *p;
7463    UINT i;
7464    // 引数チェック
7465    if (s == NULL || f == NULL)
7466    {
7467        return;
7468    }
7469
7470    if (f->Me == false)
7471    {
7472        p = NewPack();
7473
7474        PackAddStr(p, "HubName", h->Name);
7475
7476        p = SiCallTask(f, p, "deletehub");
7477        FreePack(p);
7478    }
7479
7480    LockList(f->HubList);
7481    {
7482        for (i = 0;i < LIST_NUM(f->HubList);i++)
7483        {
7484            HUB_LIST *hh = LIST_DATA(f->HubList, i);
7485            if (StrCmpi(hh->Name, h->Name) == 0)
7486            {
7487                Free(hh);
7488                Delete(f->HubList, hh);
7489            }
7490        }
7491    }
7492    UnlockList(f->HubList);
7493}
7494
7495// HUB 更新指令送信
7496void SiCallUpdateHub(SERVER *s, FARM_MEMBER *f, HUB *h)
7497{
7498    PACK *p;
7499    // 引数チェック
7500    if (s == NULL || f == NULL)
7501    {
7502        return;
7503    }
7504
7505    if (f->Me == false)
7506    {
7507        p = NewPack();
7508
7509        SiPackAddCreateHub(p, h);
7510
7511        p = SiCallTask(f, p, "updatehub");
7512        FreePack(p);
7513    }
7514}
7515
7516// チケット作成指令送信
7517void SiCallCreateTicket(SERVER *s, FARM_MEMBER *f, char *hubname, char *username, char *realusername, POLICY *policy, UCHAR *ticket, UINT counter, char *groupname)
7518{
7519    PACK *p;
7520    char name[MAX_SESSION_NAME_LEN + 1];
7521    char hub_name_upper[MAX_SIZE];
7522    char user_name_upper[MAX_USERNAME_LEN + 1];
7523    char ticket_str[MAX_SIZE];
7524    UINT point;
7525    // 引数チェック
7526    if (s == NULL || f == NULL || realusername == NULL || hubname == NULL || username == NULL || policy == NULL || ticket == NULL)
7527    {
7528        return;
7529    }
7530    if (groupname == NULL)
7531    {
7532        groupname = "";
7533    }
7534
7535    p = NewPack();
7536    PackAddStr(p, "HubName", hubname);
7537    PackAddStr(p, "UserName", username);
7538    PackAddStr(p, "groupname", groupname);
7539    PackAddStr(p, "RealUserName", realusername);
7540    OutRpcPolicy(p, policy);
7541    PackAddData(p, "Ticket", ticket, SHA1_SIZE);
7542
7543    BinToStr(ticket_str, sizeof(ticket_str), ticket, SHA1_SIZE);
7544
7545    StrCpy(hub_name_upper, sizeof(hub_name_upper), hubname);
7546    StrUpper(hub_name_upper);
7547    StrCpy(user_name_upper, sizeof(user_name_upper), username);
7548    StrUpper(user_name_upper);
7549    Format(name, sizeof(name), "SID-%s-%u", user_name_upper,
7550        counter);
7551    PackAddStr(p, "SessionName", name);
7552
7553    p = SiCallTask(f, p, "createticket");
7554
7555    SLog(s->Cedar, "LS_TICKET_1", f->hostname, hubname, username, realusername, name, ticket_str);
7556
7557    point = PackGetInt(p, "Point");
7558    if (point != 0)
7559    {
7560        f->Point = point;
7561        f->NumSessions++;
7562    }
7563
7564    FreePack(p);
7565}
7566
7567// MAC アドレス削除指令送信
7568void SiCallDeleteMacTable(SERVER *s, FARM_MEMBER *f, char *hubname, UINT key)
7569{
7570    PACK *p;
7571    // 引数チェック
7572    if (s == NULL || f == NULL || hubname == NULL)
7573    {
7574        return;
7575    }
7576
7577    p = NewPack();
7578    PackAddStr(p, "HubName", hubname);
7579    PackAddInt(p, "Key", key);
7580
7581    p = SiCallTask(f, p, "deletemactable");
7582
7583    FreePack(p);
7584}
7585
7586// IP アドレス削除指令送信
7587void SiCallDeleteIpTable(SERVER *s, FARM_MEMBER *f, char *hubname, UINT key)
7588{
7589    PACK *p;
7590    // 引数チェック
7591    if (s == NULL || f == NULL || hubname == NULL)
7592    {
7593        return;
7594    }
7595
7596    p = NewPack();
7597    PackAddStr(p, "HubName", hubname);
7598    PackAddInt(p, "Key", key);
7599
7600    p = SiCallTask(f, p, "deleteiptable");
7601
7602    FreePack(p);
7603}
7604
7605// セッション削除指令送信
7606void SiCallDeleteSession(SERVER *s, FARM_MEMBER *f, char *hubname, char *session_name)
7607{
7608    PACK *p;
7609    // 引数チェック
7610    if (s == NULL || f == NULL || hubname == NULL || session_name == NULL)
7611    {
7612        return;
7613    }
7614
7615    p = NewPack();
7616    PackAddStr(p, "HubName", hubname);
7617    PackAddStr(p, "SessionName", session_name);
7618
7619    p = SiCallTask(f, p, "deletesession");
7620
7621    FreePack(p);
7622}
7623
7624// IP テーブル列挙指令送信
7625void SiCallEnumIpTable(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_ENUM_IP_TABLE *t)
7626{
7627    PACK *p;
7628    UINT i;
7629    // 引数チェック
7630    if (s == NULL || f == NULL || hubname == NULL || t == NULL)
7631    {
7632        return;
7633    }
7634
7635    p = NewPack();
7636    PackAddStr(p, "HubName", hubname);
7637
7638    p = SiCallTask(f, p, "enumiptable");
7639
7640    Zero(t, sizeof(RPC_ENUM_IP_TABLE));
7641    InRpcEnumIpTable(t, p);
7642
7643    for (i = 0;i < t->NumIpTable;i++)
7644    {
7645        t->IpTables[i].RemoteItem = true;
7646        StrCpy(t->IpTables[i].RemoteHostname, sizeof(t->IpTables[i].RemoteHostname),
7647            f->hostname);
7648    }
7649
7650    FreePack(p);
7651}
7652
7653// MAC テーブル列挙指令送信
7654void SiCallEnumMacTable(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_ENUM_MAC_TABLE *t)
7655{
7656    PACK *p;
7657    UINT i;
7658    // 引数チェック
7659    if (s == NULL || f == NULL || hubname == NULL || t == NULL)
7660    {
7661        return;
7662    }
7663
7664    p = NewPack();
7665    PackAddStr(p, "HubName", hubname);
7666
7667    p = SiCallTask(f, p, "enummactable");
7668
7669    Zero(t, sizeof(RPC_ENUM_MAC_TABLE));
7670    InRpcEnumMacTable(t, p);
7671
7672    for (i = 0;i < t->NumMacTable;i++)
7673    {
7674        t->MacTables[i].RemoteItem = true;
7675        StrCpy(t->MacTables[i].RemoteHostname, sizeof(t->MacTables[i].RemoteHostname),
7676            f->hostname);
7677    }
7678
7679    FreePack(p);
7680}
7681
7682// SecureNAT 状況の取得指令送信
7683void SiCallGetNatStatus(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_NAT_STATUS *t)
7684{
7685    PACK *p;
7686    // 引数チェック
7687    if (s == NULL || f == NULL || hubname == NULL || t == NULL)
7688    {
7689        return;
7690    }
7691
7692    p = NewPack();
7693    PackAddStr(p, "HubName", hubname);
7694
7695    p = SiCallTask(f, p, "getnatstatus");
7696
7697    Zero(t, sizeof(RPC_NAT_STATUS));
7698    InRpcNatStatus(t, p);
7699
7700    FreePack(p);
7701}
7702
7703// DHCP エントリ列挙指令送信
7704void SiCallEnumDhcp(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_ENUM_DHCP *t)
7705{
7706    PACK *p;
7707    // 引数チェック
7708    if (s == NULL || f == NULL || hubname == NULL || t == NULL)
7709    {
7710        return;
7711    }
7712
7713    p = NewPack();
7714    PackAddStr(p, "HubName", hubname);
7715
7716    p = SiCallTask(f, p, "enumdhcp");
7717
7718    Zero(t, sizeof(RPC_ENUM_DHCP));
7719    InRpcEnumDhcp(t, p);
7720
7721    FreePack(p);
7722}
7723
7724// NAT エントリ列挙指令送信
7725void SiCallEnumNat(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_ENUM_NAT *t)
7726{
7727    PACK *p;
7728    // 引数チェック
7729    if (s == NULL || f == NULL || hubname == NULL || t == NULL)
7730    {
7731        return;
7732    }
7733
7734    p = NewPack();
7735    PackAddStr(p, "HubName", hubname);
7736
7737    p = SiCallTask(f, p, "enumnat");
7738
7739    Zero(t, sizeof(RPC_ENUM_NAT));
7740    InRpcEnumNat(t, p);
7741
7742    FreePack(p);
7743}
7744
7745// セッション列挙指令送信
7746void SiCallEnumSession(SERVER *s, FARM_MEMBER *f, char *hubname, RPC_ENUM_SESSION *t)
7747{
7748    PACK *p;
7749    UINT i;
7750    // 引数チェック
7751    if (s == NULL || f == NULL || hubname == NULL || t == NULL)
7752    {
7753        return;
7754    }
7755
7756    p = NewPack();
7757    PackAddStr(p, "HubName", hubname);
7758
7759    p = SiCallTask(f, p, "enumsession");
7760
7761    Zero(t, sizeof(RPC_ENUM_SESSION));
7762    InRpcEnumSession(t, p);
7763
7764    for (i = 0;i < t->NumSession;i++)
7765    {
7766        t->Sessions[i].RemoteSession = true;
7767        StrCpy(t->Sessions[i].RemoteHostname, sizeof(t->Sessions[i].RemoteHostname),
7768            f->hostname);
7769    }
7770
7771    FreePack(p);
7772}
7773
7774// HUB 作成指令送信
7775void SiCallCreateHub(SERVER *s, FARM_MEMBER *f, HUB *h)
7776{
7777    PACK *p;
7778    HUB_LIST *hh;
7779    // 引数チェック
7780    if (s == NULL || f == NULL)
7781    {
7782        return;
7783    }
7784
7785    if (f->Me == false)
7786    {
7787        p = NewPack();
7788
7789        SiPackAddCreateHub(p, h);
7790
7791        p = SiCallTask(f, p, "createhub");
7792        FreePack(p);
7793    }
7794
7795    hh = ZeroMalloc(sizeof(HUB_LIST));
7796    hh->DynamicHub = (h->Type == HUB_TYPE_FARM_DYNAMIC ? true : false);
7797    StrCpy(hh->Name, sizeof(hh->Name), h->Name);
7798    hh->FarmMember = f;
7799
7800    LockList(f->HubList);
7801    {
7802        bool exists = false;
7803        UINT i;
7804        for (i = 0;i < LIST_NUM(f->HubList);i++)
7805        {
7806            HUB_LIST *t = LIST_DATA(f->HubList, i);
7807            if (StrCmpi(t->Name, hh->Name) == 0)
7808            {
7809                exists = true;
7810            }
7811        }
7812        if (exists == false)
7813        {
7814            Add(f->HubList, hh);
7815        }
7816        else
7817        {
7818            Free(hh);
7819        }
7820    }
7821    UnlockList(f->HubList);
7822}
7823
7824// HUB 作成用 PACK の書き込み
7825void SiPackAddCreateHub(PACK *p, HUB *h)
7826{
7827    UINT i;
7828    UINT max_session;
7829    SERVER *s;
7830    LICENSE_STATUS license;
7831    // 引数チェック
7832    if (p == NULL || h == NULL)
7833    {
7834        return;
7835    }
7836
7837    Zero(&license, sizeof(license));
7838    s = h->Cedar->Server;
7839    if (s != NULL)
7840    {
7841        LiParseCurrentLicenseStatus(s->LicenseSystem, &license);
7842    }
7843
7844    PackAddStr(p, "HubName", h->Name);
7845    PackAddInt(p, "HubType", h->Type);
7846
7847    max_session = h->Option->MaxSession;
7848
7849    if (GetHubAdminOption(h, "max_sessions") != 0)
7850    {
7851        if (max_session == 0)
7852        {
7853            max_session = GetHubAdminOption(h, "max_sessions");
7854        }
7855        else
7856        {
7857            max_session = MIN(max_session, GetHubAdminOption(h, "max_sessions"));
7858        }
7859    }
7860
7861    PackAddInt(p, "MaxSession", max_session);
7862
7863    if (GetHubAdminOption(h, "max_sessions_client_bridge_apply") != 0 || license.CarrierEdition)
7864    {
7865        PackAddInt(p, "MaxSessionClient", GetHubAdminOption(h, "max_sessions_client"));
7866        PackAddInt(p, "MaxSessionBridge", GetHubAdminOption(h, "max_sessions_bridge"));
7867        PackAddBool(p, "MaxSessionClientBridgeApply", true);
7868    }
7869    else
7870    {
7871        PackAddInt(p, "MaxSessionClient", INFINITE);
7872        PackAddInt(p, "MaxSessionBridge", INFINITE);
7873    }
7874
7875    PackAddBool(p, "NoArpPolling", h->Option->NoArpPolling);
7876    PackAddBool(p, "NoIPv6AddrPolling", h->Option->NoIPv6AddrPolling);
7877    PackAddBool(p, "NoIpTable", h->Option->NoIpTable);
7878    PackAddBool(p, "NoEnum", h->Option->NoEnum);
7879    PackAddBool(p, "FilterPPPoE", h->Option->FilterPPPoE);
7880    PackAddBool(p, "YieldAfterStorePacket", h->Option->YieldAfterStorePacket);
7881    PackAddBool(p, "NoSpinLockForPacketDelay", h->Option->NoSpinLockForPacketDelay);
7882    PackAddInt(p, "BroadcastStormDetectionThreshold", h->Option->BroadcastStormDetectionThreshold);
7883    PackAddInt(p, "ClientMinimumRequiredBuild", h->Option->ClientMinimumRequiredBuild);
7884    PackAddBool(p, "FixForDLinkBPDU", h->Option->FixForDLinkBPDU);
7885    PackAddBool(p, "NoLookBPDUBridgeId", h->Option->NoLookBPDUBridgeId);
7886    PackAddBool(p, "NoManageVlanId", h->Option->NoManageVlanId);
7887    PackAddInt(p, "VlanTypeId", h->Option->VlanTypeId);
7888    PackAddBool(p, "FilterOSPF", h->Option->FilterOSPF);
7889    PackAddBool(p, "FilterIPv4", h->Option->FilterIPv4);
7890    PackAddBool(p, "FilterIPv6", h->Option->FilterIPv6);
7891    PackAddBool(p, "FilterNonIP", h->Option->FilterNonIP);
7892    PackAddBool(p, "NoIPv4PacketLog", h->Option->NoIPv4PacketLog);
7893    PackAddBool(p, "NoIPv6PacketLog", h->Option->NoIPv6PacketLog);
7894    PackAddBool(p, "FilterBPDU", h->Option->FilterBPDU);
7895    PackAddBool(p, "NoIPv6DefaultRouterInRAWhenIPv6", h->Option->NoIPv6DefaultRouterInRAWhenIPv6);
7896    PackAddBool(p, "NoMacAddressLog", h->Option->NoMacAddressLog);
7897    PackAddBool(p, "ManageOnlyPrivateIP", h->Option->ManageOnlyPrivateIP);
7898    PackAddBool(p, "ManageOnlyLocalUnicastIPv6", h->Option->ManageOnlyLocalUnicastIPv6);
7899    PackAddBool(p, "DisableIPParsing", h->Option->DisableIPParsing);
7900
7901    PackAddInt(p, "SavePacketLog", h->LogSetting.SavePacketLog);
7902    PackAddInt(p, "PacketLogSwitchType", h->LogSetting.PacketLogSwitchType);
7903    for (i = 0;i < NUM_PACKET_LOG;i++)
7904    {
7905        PackAddIntEx(p, "PacketLogConfig", h->LogSetting.PacketLogConfig[i], i, NUM_PACKET_LOG);
7906    }
7907    PackAddInt(p, "SaveSecurityLog", h->LogSetting.SaveSecurityLog);
7908    PackAddInt(p, "SecurityLogSwitchType", h->LogSetting.SecurityLogSwitchType);
7909    PackAddData(p, "HashedPassword", h->HashedPassword, SHA1_SIZE);
7910    PackAddData(p, "SecurePassword", h->SecurePassword, SHA1_SIZE);
7911
7912    SiAccessListToPack(p, h->AccessList);
7913
7914    if (h->EnableSecureNAT)
7915    {
7916        PackAddBool(p, "EnableSecureNAT", h->EnableSecureNAT);
7917        OutVhOption(p, h->SecureNATOption);
7918    }
7919}
7920
7921// HUB の設定が更新された
7922void SiHubUpdateProc(HUB *h)
7923{
7924    SERVER *s;
7925    UINT i;
7926    // 引数チェック
7927    if (h == NULL || h->Cedar->Server == NULL || h->Cedar->Server->ServerType != SERVER_TYPE_FARM_CONTROLLER)
7928    {
7929        return;
7930    }
7931
7932    s = h->Cedar->Server;
7933
7934    if (s->FarmMemberList == NULL)
7935    {
7936        return;
7937    }
7938
7939    if (h->LastVersion != h->CurrentVersion || h->CurrentVersion == 0)
7940    {
7941        if (h->CurrentVersion == 0)
7942        {
7943            h->CurrentVersion = 1;
7944        }
7945        h->LastVersion = h->CurrentVersion;
7946
7947        LockList(s->FarmMemberList);
7948        {
7949            // すべてのメンバで HUB を更新する
7950            for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
7951            {
7952                FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
7953                if (f->Me == false)
7954                {
7955                    SiCallUpdateHub(s, f, h);
7956                }
7957            }
7958        }
7959        UnlockList(s->FarmMemberList);
7960    }
7961
7962    if (h->Offline == false)
7963    {
7964        SiHubOnlineProc(h);
7965    }
7966}
7967
7968// HUB がオンラインになった
7969void SiHubOnlineProc(HUB *h)
7970{
7971    SERVER *s;
7972    UINT i;
7973    // 引数チェック
7974    if (h == NULL || h->Cedar->Server == NULL || h->Cedar->Server->ServerType != SERVER_TYPE_FARM_CONTROLLER)
7975    {
7976        // ファームコントローラ以外では処理しない
7977        return;
7978    }
7979
7980    s = h->Cedar->Server;
7981
7982    if (s->FarmMemberList == NULL)
7983    {
7984        return;
7985    }
7986
7987    LockList(s->FarmMemberList);
7988    {
7989        if (h->Type == HUB_TYPE_FARM_STATIC)
7990        {
7991            // スタティック HUB
7992            // すべてのメンバで HUB を作成する
7993            for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
7994            {
7995                UINT j;
7996                bool exists = false;
7997                FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
7998
7999                LockList(f->HubList);
8000                {
8001                    for (j = 0;j < LIST_NUM(f->HubList);j++)
8002                    {
8003                        HUB_LIST *hh = LIST_DATA(f->HubList, j);
8004                        if (StrCmpi(hh->Name, h->Name) == 0)
8005                        {
8006                            exists = true;
8007                        }
8008                    }
8009                }
8010                UnlockList(f->HubList);
8011
8012                if (exists == false)
8013                {
8014                    SiCallCreateHub(s, f, h);
8015                }
8016            }
8017        }
8018    }
8019    UnlockList(s->FarmMemberList);
8020}
8021
8022// HUB がオフラインになった
8023void SiHubOfflineProc(HUB *h)
8024{
8025    SERVER *s;
8026    char hubname[MAX_HUBNAME_LEN + 1];
8027    UINT i;
8028    // 引数チェック
8029    if (h == NULL || h->Cedar->Server == NULL || h->Cedar->Server->ServerType != SERVER_TYPE_FARM_CONTROLLER)
8030    {
8031        // ファームコントローラ以外では処理しない
8032        return;
8033    }
8034
8035    s = h->Cedar->Server;
8036
8037    if (s->FarmMemberList == NULL)
8038    {
8039        return;
8040    }
8041
8042    StrCpy(hubname, sizeof(hubname), h->Name);
8043
8044    LockList(s->FarmMemberList);
8045    {
8046        // すべてのメンバで HUB を停止する
8047        for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
8048        {
8049            FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
8050            SiCallDeleteHub(s, f, h);
8051        }
8052    }
8053    UnlockList(s->FarmMemberList);
8054}
8055
8056// アクセスを PACK に変換する
8057void SiAccessToPack(PACK *p, ACCESS *a, UINT i, UINT total)
8058{
8059    // 引数チェック
8060    if (p == NULL || a == NULL)
8061    {
8062        return;
8063    }
8064
8065    PackAddUniStrEx(p, "Note", a->Note, i, total);
8066    PackAddIntEx(p, "Active", a->Active, i, total);
8067    PackAddIntEx(p, "Priority", a->Priority, i, total);
8068    PackAddIntEx(p, "Discard", a->Discard, i, total);
8069    if (a->IsIPv6)
8070    {
8071        PackAddIp32Ex(p, "SrcIpAddress", 0xFDFFFFDF, i, total);
8072        PackAddIp32Ex(p, "SrcSubnetMask", 0xFFFFFFFF, i, total);
8073        PackAddIp32Ex(p, "DestIpAddress", 0xFDFFFFDF, i, total);
8074        PackAddIp32Ex(p, "DestSubnetMask", 0xFFFFFFFF, i, total);
8075    }
8076    else
8077    {
8078        PackAddIp32Ex(p, "SrcIpAddress", a->SrcIpAddress, i, total);
8079        PackAddIp32Ex(p, "SrcSubnetMask", a->SrcSubnetMask, i, total);
8080        PackAddIp32Ex(p, "DestIpAddress", a->DestIpAddress, i, total);
8081        PackAddIp32Ex(p, "DestSubnetMask", a->DestSubnetMask, i, total);
8082    }
8083    PackAddIntEx(p, "Protocol", a->Protocol, i, total);
8084    PackAddIntEx(p, "SrcPortStart", a->SrcPortStart, i, total);
8085    PackAddIntEx(p, "SrcPortEnd", a->SrcPortEnd, i, total);
8086    PackAddIntEx(p, "DestPortStart", a->DestPortStart, i, total);
8087    PackAddIntEx(p, "DestPortEnd", a->DestPortEnd, i, total);
8088    PackAddStrEx(p, "SrcUsername", a->SrcUsername, i, total);
8089    PackAddStrEx(p, "DestUsername", a->DestUsername, i, total);
8090    PackAddBoolEx(p, "CheckSrcMac", a->CheckSrcMac, i, total);
8091    PackAddDataEx(p, "SrcMacAddress", a->SrcMacAddress, sizeof(a->SrcMacAddress), i, total);
8092    PackAddDataEx(p, "SrcMacMask", a->SrcMacMask, sizeof(a->SrcMacMask), i, total);
8093    PackAddBoolEx(p, "CheckDstMac", a->CheckDstMac, i, total);
8094    PackAddDataEx(p, "DstMacAddress", a->DstMacAddress, sizeof(a->DstMacAddress), i, total);
8095    PackAddDataEx(p, "DstMacMask", a->DstMacMask, sizeof(a->DstMacMask), i, total);
8096    PackAddBoolEx(p, "CheckTcpState", a->CheckTcpState, i, total);
8097    PackAddBoolEx(p, "Established", a->Established, i, total);
8098    PackAddIntEx(p, "Delay", a->Delay, i, total);
8099    PackAddIntEx(p, "Jitter", a->Jitter, i, total);
8100    PackAddIntEx(p, "Loss", a->Loss, i, total);
8101    PackAddBoolEx(p, "IsIPv6", a->IsIPv6, i, total);
8102    if (a->IsIPv6)
8103    {
8104        PackAddIp6AddrEx(p, "SrcIpAddress6", &a->SrcIpAddress6, i, total);
8105        PackAddIp6AddrEx(p, "SrcSubnetMask6", &a->SrcSubnetMask6, i, total);
8106        PackAddIp6AddrEx(p, "DestIpAddress6", &a->DestIpAddress6, i, total);
8107        PackAddIp6AddrEx(p, "DestSubnetMask6", &a->DestSubnetMask6, i, total);
8108    }
8109    else
8110    {
8111        IPV6_ADDR zero;
8112
8113        Zero(&zero, sizeof(zero));
8114
8115        PackAddIp6AddrEx(p, "SrcIpAddress6", &zero, i, total);
8116        PackAddIp6AddrEx(p, "SrcSubnetMask6", &zero, i, total);
8117        PackAddIp6AddrEx(p, "DestIpAddress6", &zero, i, total);
8118        PackAddIp6AddrEx(p, "DestSubnetMask6", &zero, i, total);
8119    }
8120}
8121
8122// PACK に入っているアクセス個数を取得
8123UINT SiNumAccessFromPack(PACK *p)
8124{
8125    // 引数チェック
8126    if (p == NULL)
8127    {
8128        return 0;
8129    }
8130
8131    return PackGetIndexCount(p, "Active");
8132}
8133
8134// PACK をアクセスに変換する
8135ACCESS *SiPackToAccess(PACK *p, UINT i)
8136{
8137    ACCESS *a;
8138    // 引数チェック
8139    if (p == NULL)
8140    {
8141        return NULL;
8142    }
8143
8144    a = ZeroMalloc(sizeof(ACCESS));
8145
8146    PackGetUniStrEx(p, "Note", a->Note, sizeof(a->Note), i);
8147    a->Active = PackGetIntEx(p, "Active", i);
8148    a->Priority = PackGetIntEx(p, "Priority", i);
8149    a->Discard = PackGetIntEx(p, "Discard", i);
8150    a->SrcIpAddress = PackGetIp32Ex(p, "SrcIpAddress", i);
8151    a->SrcSubnetMask = PackGetIp32Ex(p, "SrcSubnetMask", i);
8152    a->DestIpAddress = PackGetIp32Ex(p, "DestIpAddress", i);
8153    a->DestSubnetMask = PackGetIp32Ex(p, "DestSubnetMask", i);
8154    a->Protocol = PackGetIntEx(p, "Protocol", i);
8155    a->SrcPortStart = PackGetIntEx(p, "SrcPortStart", i);
8156    a->SrcPortEnd = PackGetIntEx(p, "SrcPortEnd", i);
8157    a->DestPortStart = PackGetIntEx(p, "DestPortStart", i);
8158    a->DestPortEnd = PackGetIntEx(p, "DestPortEnd", i);
8159    PackGetStrEx(p, "SrcUsername", a->SrcUsername, sizeof(a->SrcUsername), i);
8160    PackGetStrEx(p, "DestUsername", a->DestUsername, sizeof(a->DestUsername), i);
8161    a->CheckSrcMac = PackGetBoolEx(p, "CheckSrcMac", i);
8162    PackGetDataEx2(p, "SrcMacAddress", a->SrcMacAddress, sizeof(a->SrcMacAddress), i);
8163    PackGetDataEx2(p, "SrcMacMask", a->SrcMacMask, sizeof(a->SrcMacMask), i);
8164    a->CheckDstMac = PackGetBoolEx(p, "CheckDstMac", i);
8165    PackGetDataEx2(p, "DstMacAddress", a->DstMacAddress, sizeof(a->DstMacAddress), i);
8166    PackGetDataEx2(p, "DstMacMask", a->DstMacMask, sizeof(a->DstMacMask), i);
8167    a->CheckTcpState = PackGetBoolEx(p, "CheckTcpState", i);
8168    a->Established = PackGetBoolEx(p, "Established", i);
8169    a->Delay = PackGetIntEx(p, "Delay", i);
8170    a->Jitter = PackGetIntEx(p, "Jitter", i);
8171    a->Loss = PackGetIntEx(p, "Loss", i);
8172    a->IsIPv6 = PackGetBoolEx(p, "IsIPv6", i);
8173    if (a->IsIPv6)
8174    {
8175        PackGetIp6AddrEx(p, "SrcIpAddress6", &a->SrcIpAddress6, i);
8176        PackGetIp6AddrEx(p, "SrcSubnetMask6", &a->SrcSubnetMask6, i);
8177        PackGetIp6AddrEx(p, "DestIpAddress6", &a->DestIpAddress6, i);
8178        PackGetIp6AddrEx(p, "DestSubnetMask6", &a->DestSubnetMask6, i);
8179    }
8180
8181    return a;
8182}
8183
8184// アクセスリストを PACK に変換する
8185void SiAccessListToPack(PACK *p, LIST *o)
8186{
8187    // 引数チェック
8188    if (p == NULL || o == NULL)
8189    {
8190        return;
8191    }
8192
8193    LockList(o);
8194    {
8195        UINT i;
8196        for (i = 0;i < LIST_NUM(o);i++)
8197        {
8198            ACCESS *a = LIST_DATA(o, i);
8199            SiAccessToPack(p, a, i, LIST_NUM(o));
8200        }
8201    }
8202    UnlockList(o);
8203}
8204
8205// 指定した HUB をホストしているメンバを取得する
8206FARM_MEMBER *SiGetHubHostingMember(SERVER *s, HUB *h, bool admin_mode)
8207{
8208    FARM_MEMBER *ret = NULL;
8209    char name[MAX_SIZE];
8210    // 引数チェック
8211    if (s == NULL || h == NULL)
8212    {
8213        return NULL;
8214    }
8215
8216    StrCpy(name, sizeof(name), h->Name);
8217
8218    if (h->Type == HUB_TYPE_FARM_STATIC)
8219    {
8220        // スタティック HUB の場合 任意のメンバを選択すれば良い
8221        if (admin_mode == false)
8222        {
8223            ret = SiGetNextFarmMember(s);
8224        }
8225        else
8226        {
8227            UINT i;
8228            ret = NULL;
8229
8230            for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
8231            {
8232                FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
8233                if (f->Me)
8234                {
8235                    ret = f;
8236                    break;
8237                }
8238            }
8239        }
8240    }
8241    else
8242    {
8243        // ダイナミック HUB の場合
8244        // すでに HUB をホストしているメンバがあるかどうか調べる
8245        UINT i;
8246
8247        for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)
8248        {
8249            FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);
8250            HUB_LIST *hh, t;
8251            StrCpy(t.Name, sizeof(t.Name), name);
8252            LockList(f->HubList);
8253            {
8254                hh = Search(f->HubList, &t);
8255                if (hh != NULL)
8256                {
8257                    // 発見した
8258                    ret = f;
8259                }
8260            }
8261            UnlockList(f->HubList);
8262        }
8263
8264        if (ret == NULL)
8265        {
8266            // 新しく HUB をホストさせる
8267            FARM_MEMBER *f;
8268
8269            // ホストさせるメンバの選択
8270            ret = SiGetNextFarmMember(s);
8271
8272            f = ret;
8273            if (f != NULL)
8274            {
8275                // HUB 作成指令
8276                SiAddHubCreateHistory(s, name);
8277                SiCallCreateHub(s, f, h);
8278                SiCallUpdateHub(s, f, h);
8279            }
8280        }
8281    }
8282
8283    return ret;
8284}
8285
8286// タスクが呼び出された
8287PACK *SiCalledTask(FARM_CONTROLLER *f, PACK *p, char *taskname)
8288{
8289    PACK *ret;
8290    SERVER *s;
8291    // 引数チェック
8292    if (f == NULL || p == NULL || taskname == NULL)
8293    {
8294        return NULL;
8295    }
8296
8297    ret = NULL;
8298    s = f->Server;
8299
8300    if (StrCmpi(taskname, "noop") == 0)
8301    {
8302        // NO OPERATION
8303        ret = NewPack();
8304    }
8305    else
8306    {
8307        Debug("Task Called: [%s].\n", taskname);
8308        if (StrCmpi(taskname, "createhub") == 0)
8309        {
8310            SiCalledCreateHub(s, p);
8311            ret = NewPack();
8312        }
8313        else if (StrCmpi(taskname, "deletehub") == 0)
8314        {
8315            SiCalledDeleteHub(s, p);
8316            ret = NewPack();
8317        }
8318        else if (StrCmpi(taskname, "enumhub") == 0)
8319        {
8320            ret = NewPack();
8321            SiCalledEnumHub(s, ret, p);
8322        }
8323        else if (StrCmpi(taskname, "updatehub") == 0)
8324        {
8325            SiCalledUpdateHub(s, p);
8326            ret = NewPack();
8327        }
8328        else if (StrCmpi(taskname, "createticket") == 0)
8329        {
8330            ret = SiCalledCreateTicket(s, p);
8331        }
8332        else if (StrCmpi(taskname, "enumnat") == 0)
8333        {
8334            ret = SiCalledEnumNat(s, p);
8335        }
8336        else if (StrCmpi(taskname, "enumdhcp") == 0)
8337        {
8338            ret = SiCalledEnumDhcp(s, p);
8339        }
8340        else if (StrCmpi(taskname, "getnatstatus") == 0)
8341        {
8342            ret = SiCalledGetNatStatus(s, p);
8343        }
8344        else if (StrCmpi(taskname, "enumsession") == 0)
8345        {
8346            ret = SiCalledEnumSession(s, p);
8347        }
8348        else if (StrCmpi(taskname, "deletesession") == 0)
8349        {
8350            SiCalledDeleteSession(s, p);
8351            ret = NewPack();
8352        }
8353        else if (StrCmpi(taskname, "deletemactable") == 0)
8354        {
8355            SiCalledDeleteMacTable(s, p);
8356            ret = NewPack();
8357        }
8358        else if (StrCmpi(taskname, "deleteiptable") == 0)
8359        {
8360            SiCalledDeleteIpTable(s, p);
8361            ret = NewPack();
8362        }
8363        else if (StrCmpi(taskname, "enummactable") == 0)
8364        {
8365            ret = SiCalledEnumMacTable(s, p);
8366        }
8367        else if (StrCmpi(taskname, "enumiptable") == 0)
8368        {
8369            ret = SiCalledEnumIpTable(s, p);
8370        }
8371        else if (StrCmpi(taskname, "getsessionstatus") == 0)
8372        {
8373            ret = SiCalledGetSessionStatus(s, p);
8374        }
8375        else if (StrCmpi(taskname, "enumlogfilelist") == 0)
8376        {
8377            ret = SiCalledEnumLogFileList(s, p);
8378        }
8379        else if (StrCmpi(taskname, "readlogfile") == 0)
8380        {
8381            ret = SiCalledReadLogFile(s, p);
8382        }
8383    }
8384
8385    return ret;
8386}
8387
8388// タスクを呼び出す
8389PACK *SiCallTask(FARM_MEMBER *f, PACK *p, char *taskname)
8390{
8391    PACK *ret;
8392    char tmp[MAX_PATH];
8393    // 引数チェック
8394    if (f == NULL || p == NULL || taskname == NULL)
8395    {
8396        return NULL;
8397    }
8398
8399    PackAddStr(p, "taskname", taskname);
8400
8401    Debug("Call Task [%s] (%s)\n", taskname, f->hostname);
8402
8403    Format(tmp, sizeof(tmp), "CLUSTER_CALL: Entering Call [%s] to %s", taskname, f->hostname);
8404    SiDebugLog(f->Cedar->Server, tmp);
8405
8406    ret = SiExecTask(f, p);
8407
8408    Format(tmp, sizeof(tmp), "CLUSTER_CALL: Leaving Call [%s] to %s", taskname, f->hostname);
8409    SiDebugLog(f->Cedar->Server, tmp);
8410
8411    return ret;
8412}
8413
8414// タスク待ちうけプロシージャ (メイン処理)
8415void SiAcceptTasksFromControllerMain(FARM_CONTROLLER *f, SOCK *sock)
8416{
8417    PACK *request;
8418    PACK *response;
8419    char taskname[MAX_SIZE];
8420    // 引数チェック
8421    if (f == NULL || sock == NULL)
8422    {
8423        return;
8424    }
8425
8426    while (true)
8427    {
8428        bool ret;
8429        // PACK を受信する
8430        request = HttpClientRecv(sock);
8431        if (request == NULL)
8432        {
8433            // 切断
8434            return;
8435        }
8436
8437        response = NULL;
8438
8439        // 名前の取得
8440        if (PackGetStr(request, "taskname", taskname, sizeof(taskname)))
8441        {
8442            Lock(f->Server->TasksFromFarmControllerLock);
8443            {
8444                response = SiCalledTask(f, request, taskname);
8445            }
8446            Unlock(f->Server->TasksFromFarmControllerLock);
8447        }
8448
8449        FreePack(request);
8450
8451        // 応答を返す
8452        if (response == NULL)
8453        {
8454            response = NewPack();
8455        }
8456        else
8457        {
8458            PackAddInt(response, "succeed", 1);
8459        }
8460
8461        ret = HttpClientSend(sock, response);
8462        FreePack(response);
8463
8464        if (ret == false)
8465        {
8466            // 切断
8467            return;
8468        }
8469    }
8470}
8471
8472// タスク待ちうけプロシージャ
8473void SiAcceptTasksFromController(FARM_CONTROLLER *f, SOCK *sock)
8474{
8475    UINT i;
8476    HUB **hubs;
8477    UINT num_hubs;
8478    CEDAR *c;
8479    SERVER *s;
8480    // 引数チェック
8481    if (f == NULL || sock == NULL)
8482    {
8483        return;
8484    }
8485
8486    s = f->Server;
8487    c = s->Cedar;
8488
8489    // メイン処理
8490    SiAcceptTasksFromControllerMain(f, sock);
8491
8492    // コントローラとの接続が切断されたためすべての仮想 HUB を停止する
8493    LockList(c->HubList);
8494    {
8495        hubs = ToArray(c->HubList);
8496        num_hubs = LIST_NUM(c->HubList);
8497        for (i = 0;i < num_hubs;i++)
8498        {
8499            AddRef(hubs[i]->ref);
8500        }
8501    }
8502    UnlockList(c->HubList);
8503
8504    for (i = 0;i < num_hubs;i++)
8505    {
8506        SetHubOffline(hubs[i]);
8507        DelHub(c, hubs[i]);
8508        ReleaseHub(hubs[i]);
8509    }
8510
8511    Free(hubs);
8512}
8513
8514// タスクを実行する
8515PACK *SiExecTask(FARM_MEMBER *f, PACK *p)
8516{
8517    FARM_TASK *t;
8518    // 引数チェック
8519    if (f == NULL || p == NULL)
8520    {
8521        return NULL;
8522    }
8523
8524    t = SiFarmServPostTask(f, p);
8525    if (t == NULL)
8526    {
8527        return NULL;
8528    }
8529
8530    return SiFarmServWaitTask(t);
8531}
8532
8533// タスク投入
8534FARM_TASK *SiFarmServPostTask(FARM_MEMBER *f, PACK *request)
8535{
8536    FARM_TASK *t;
8537    // 引数チェック
8538    if (f == NULL || request == NULL)
8539    {
8540        return NULL;
8541    }
8542
8543    t = ZeroMalloc(sizeof(FARM_TASK));
8544    t->CompleteEvent = NewEvent();
8545    t->Request = request;
8546
8547    LockQueue(f->TaskQueue);
8548    {
8549        if (f->Halting)
8550        {
8551            // 停止中 (失敗)
8552            UnlockQueue(f->TaskQueue);
8553            ReleaseEvent(t->CompleteEvent);
8554            Free(t);
8555            return NULL;
8556        }
8557
8558        InsertQueue(f->TaskQueue, t);
8559    }
8560    UnlockQueue(f->TaskQueue);
8561
8562    Set(f->TaskPostEvent);
8563
8564    return t;
8565}
8566
8567// タスク結果待ち
8568PACK *SiFarmServWaitTask(FARM_TASK *t)
8569{
8570    PACK *response;
8571    // 引数チェック
8572    if (t == NULL)
8573    {
8574        return NULL;
8575    }
8576
8577    Wait(t->CompleteEvent, INFINITE);
8578    ReleaseEvent(t->CompleteEvent);
8579    FreePack(t->Request);
8580
8581    response = t->Response;
8582    Free(t);
8583
8584    if (PackGetInt(response, "succeed") == 0)
8585    {
8586        // 何らかの原因でタスク呼び出しが失敗した
8587        FreePack(response);
8588        return NULL;
8589    }
8590
8591    return response;
8592}
8593
8594// ファームサーバー処理メイン
8595void SiFarmServMain(SERVER *server, SOCK *sock, FARM_MEMBER *f)
8596{
8597    UINT wait_time = SERVER_CONTROL_TCP_TIMEOUT / 2;
8598    bool send_noop = false;
8599    UINT i;
8600    CEDAR *c;
8601    // 引数チェック
8602    if (server == NULL || sock == NULL || f == NULL)
8603    {
8604        Debug("SiFarmServMain Failed.\n");
8605        return;
8606    }
8607
8608    Debug("SiFarmServMain Started.\n");
8609
8610    c = server->Cedar;
8611
8612    // メンバがコントローラに接続してきた段階で
8613    // すべてのスタティック HUB の作成指令を送信する
8614    LockList(c->HubList);
8615    {
8616        for (i = 0;i < LIST_NUM(c->HubList);i++)
8617        {
8618            HUB *h = LIST_DATA(c->HubList, i);
8619            if (h->Offline == false)
8620            {
8621                if (h->Type == HUB_TYPE_FARM_STATIC)
8622                {
8623                    PACK *p;
8624                    HUB_LIST *hh;
8625                    p = NewPack();
8626                    SiPackAddCreateHub(p, h);
8627                    PackAddStr(p, "taskname", "createhub");
8628                    HttpServerSend(sock, p);
8629                    FreePack(p);
8630                    p = HttpServerRecv(sock);
8631                    FreePack(p);
8632
8633                    p = NewPack();
8634                    SiPackAddCreateHub(p, h);
8635                    PackAddStr(p, "taskname", "updatehub");
8636                    HttpServerSend(sock, p);
8637                    FreePack(p);
8638                    p = HttpServerRecv(sock);
8639                    FreePack(p);
8640
8641                    hh = ZeroMalloc(sizeof(HUB_LIST));
8642                    hh->DynamicHub = false;
8643                    hh->FarmMember = f;
8644                    StrCpy(hh->Name, sizeof(hh->Name), h->Name);
8645                    LockList(f->HubList);
8646                    {
8647                        Add(f->HubList, hh);
8648                    }
8649                    UnlockList(f->HubList);
8650                }
8651            }
8652        }
8653    }
8654    UnlockList(c->HubList);
8655
8656    Debug("SiFarmServMain: while (true)\n");
8657
8658    while (true)
8659    {
8660        FARM_TASK *t;
8661        UINT64 tick;
8662
8663        do
8664        {
8665            // 新しいタスクが到着していないかどうか調べる
8666            LockQueue(f->TaskQueue);
8667            {
8668                t = GetNext(f->TaskQueue);
8669            }
8670            UnlockQueue(f->TaskQueue);
8671
8672            if (t != NULL)
8673            {
8674                // このタスクを処理する
8675                PACK *p = t->Request;
8676                bool ret;
8677
8678                // 送信
8679                ret = HttpServerSend(sock, p);
8680                send_noop = false;
8681
8682                if (ret == false)
8683                {
8684                    // 接続が切れた
8685                    // このタスクをキャンセルする
8686                    Set(t->CompleteEvent);
8687                    goto DISCONNECTED;
8688                }
8689
8690                // 受信
8691                p = HttpServerRecv(sock);
8692
8693                t->Response = p;
8694                Set(t->CompleteEvent);
8695
8696                send_noop = false;
8697            }
8698        }
8699        while (t != NULL);
8700
8701        if (send_noop)
8702        {
8703            // NOOP を送信する
8704            PACK *p;
8705            bool ret;
8706            p = NewPack();
8707            PackAddStr(p, "taskname", "noop");
8708
8709            ret = HttpServerSend(sock, p);
8710            FreePack(p);
8711
8712            if (ret == false)
8713            {
8714                goto DISCONNECTED;
8715            }
8716
8717            p = HttpServerRecv(sock);
8718            if (p == NULL)
8719            {
8720                goto DISCONNECTED;
8721            }
8722
8723            FreePack(p);
8724        }
8725
8726        tick = Tick64();
8727
8728        while (true)
8729        {
8730            bool break_flag;
8731            if ((tick + wait_time) <= Tick64())
8732            {
8733                break;
8734            }
8735
8736            Wait(f->TaskPostEvent, 250);
8737
8738            break_flag = false;
8739            LockQueue(f->TaskQueue);
8740            {
8741                if (f->TaskQueue->num_item != 0)
8742                {
8743                    break_flag = true;
8744                }
8745            }
8746            UnlockQueue(f->TaskQueue);
8747
8748            if (break_flag || f->Halting || server->Halt)
8749            {
8750                break;
8751            }
8752        }
8753        send_noop = true;
8754    }
8755
8756DISCONNECTED:
8757
8758    Debug("SiFarmServMain: DISCONNECTED\n");
8759
8760    f->Halting = true;
8761    // すべての未処理のタスクをキャンセルする
8762    LockQueue(f->TaskQueue);
8763    {
8764        FARM_TASK *t;
8765
8766        while (t = GetNext(f->TaskQueue))
8767        {
8768            Set(t->CompleteEvent);
8769        }
8770    }
8771    UnlockQueue(f->TaskQueue);
8772}
8773
8774// ファームメンバからの接続を処理するファームサーバー関数
8775void SiFarmServ(SERVER *server, SOCK *sock, X *cert, UINT ip, UINT num_port, UINT *ports, char *hostname, UINT point, UINT weight, UINT max_sessions)
8776{
8777    PACK *p;
8778    FARM_MEMBER *f;
8779    UINT i;
8780    char tmp[MAX_SIZE];
8781    // 引数チェック
8782    if (server == NULL || sock == NULL || cert == NULL || num_port == 0 || ports == NULL || hostname == NULL)
8783    {
8784        return;
8785    }
8786
8787    if (weight == 0)
8788    {
8789        weight = FARM_DEFAULT_WEIGHT;
8790    }
8791
8792    if (max_sessions == 0)
8793    {
8794        max_sessions = SERVER_MAX_SESSIONS;
8795    }
8796
8797    if (ip == 0)
8798    {
8799        // 公開 IP アドレスが指定されていない場合はこのファームメンバサーバーの
8800        // 接続元 IP アドレスを指定する
8801        ip = IPToUINT(&sock->RemoteIP);
8802    }
8803
8804    IPToStr32(tmp, sizeof(tmp), ip);
8805    SLog(server->Cedar, "LS_FARM_SERV_START", tmp, hostname);
8806
8807    // 成功を知らせる
8808    p = NewPack();
8809    HttpServerSend(sock, p);
8810    FreePack(p);
8811
8812    IPToStr32(tmp, sizeof(tmp), ip);
8813    Debug("Farm Member %s Connected. IP: %s\n", hostname, tmp);
8814
8815    SetTimeout(sock, SERVER_CONTROL_TCP_TIMEOUT);
8816
8817    f = ZeroMalloc(sizeof(FARM_MEMBER));
8818    f->Cedar = server->Cedar;
8819    f->Ip = ip;
8820    f->NumPort = num_port;
8821    f->Ports = ports;
8822    StrCpy(f->hostname, sizeof(f->hostname), hostname);
8823    f->ServerCert = cert;
8824    f->ConnectedTime = SystemTime64();
8825    f->Weight = weight;
8826    f->MaxSessions = max_sessions;
8827
8828    f->HubList = NewList(CompareHubList);
8829    f->Point = point;
8830
8831    f->TaskQueue = NewQueue();
8832    f->TaskPostEvent = NewEvent();
8833
8834    // リストに追加する
8835    LockList(server->FarmMemberList);
8836    {
8837        Add(server->FarmMemberList, f);
8838    }
8839    UnlockList(server->FarmMemberList);
8840
8841    // メイン処理
8842    SiFarmServMain(server, sock, f);
8843
8844    // リストから削除する
8845    LockList(server->FarmMemberList);
8846    {
8847        Delete(server->FarmMemberList, f);
8848    }
8849    UnlockList(server->FarmMemberList);
8850
8851    ReleaseQueue(f->TaskQueue);
8852    ReleaseEvent(f->TaskPostEvent);
8853
8854    for (i = 0;i < LIST_NUM(f->HubList);i++)
8855    {
8856        HUB_LIST *hh = LIST_DATA(f->HubList, i);
8857        Free(hh);
8858    }
8859
8860    ReleaseList(f->HubList);
8861
8862    Free(f);
8863
8864    SLog(server->Cedar, "LS_FARM_SERV_END", hostname);
8865}
8866
8867// HUB リストの検索
8868int CompareHubList(void *p1, void *p2)
8869{
8870    HUB_LIST *h1, *h2;
8871    if (p1 == NULL || p2 == NULL)
8872    {
8873        return 0;
8874    }
8875    h1 = *(HUB_LIST **)p1;
8876    h2 = *(HUB_LIST **)p2;
8877    if (h1 == NULL || h2 == NULL)
8878    {
8879        return 0;
8880    }
8881    return StrCmpi(h1->Name, h2->Name);
8882}
8883
8884// コントローラへの接続スレッド
8885void SiConnectToControllerThread(THREAD *thread, void *param)
8886{
8887    FARM_CONTROLLER *f;
8888    SESSION *s;
8889    CONNECTION *c;
8890    SERVER *server;
8891    bool first_failed;
8892    // 引数チェック
8893    if (thread == NULL || param == NULL)
8894    {
8895        return;
8896    }
8897
8898#ifdef  OS_WIN32
8899    MsSetThreadPriorityRealtime();
8900#endif  // OS_WIN32
8901
8902    f = (FARM_CONTROLLER *)param;
8903    f->Thread = thread;
8904    AddRef(f->Thread->ref);
8905    NoticeThreadInit(thread);
8906
8907    f->StartedTime = SystemTime64();
8908
8909    server = f->Server;
8910
8911    f->StartedTime = SystemTime64();
8912
8913    SLog(server->Cedar, "LS_FARM_CONNECT_1", server->ControllerName);
8914
8915    first_failed = true;
8916
8917    while (true)
8918    {
8919        // 接続を試行
8920        CLIENT_OPTION o;
8921
8922        f->LastError = ERR_TRYING_TO_CONNECT;
8923
8924        Zero(&o, sizeof(CLIENT_OPTION));
8925        StrCpy(o.Hostname, sizeof(o.Hostname), server->ControllerName);
8926        o.Port = server->ControllerPort;
8927        f->NumTry++;
8928
8929        Debug("Try to Connect %s (Controller).\n", server->ControllerName);
8930
8931        s = NewRpcSessionEx(server->Cedar, &o, NULL, CEDAR_SERVER_FARM_STR);
8932
8933        if (s != NULL)
8934        {
8935            // 接続成功: 認証データを送信
8936            PACK *p = NewPack();
8937            UCHAR secure_password[SHA1_SIZE];
8938            BUF *b;
8939
8940            c = s->Connection;
8941
8942            Lock(f->lock);
8943            {
8944                f->Sock = c->FirstSock;
8945                AddRef(f->Sock->ref);
8946                SetTimeout(f->Sock, SERVER_CONTROL_TCP_TIMEOUT);
8947            }
8948            Unlock(f->lock);
8949
8950            // メソッド
8951            PackAddStr(p, "method", "farm_connect");
8952            PackAddClientVersion(p, s->Connection);
8953
8954            // パスワード
8955            SecurePassword(secure_password, server->MemberPassword, s->Connection->Random);
8956            PackAddData(p, "SecurePassword", secure_password, sizeof(secure_password));
8957
8958            Lock(server->Cedar->lock);
8959            {
8960                b = XToBuf(server->Cedar->ServerX, false);
8961            }
8962            Unlock(server->Cedar->lock);
8963
8964            if (b != NULL)
8965            {
8966                char tmp[MAX_SIZE];
8967                bool ret;
8968                UINT i;
8969                // サーバー証明書
8970                PackAddBuf(p, "ServerCert", b);
8971                FreeBuf(b);
8972
8973                // 最大セッション数
8974                PackAddInt(p, "MaxSessions", GetServerCapsInt(server, "i_max_sessions"));
8975
8976                // ポイント
8977                PackAddInt(p, "Point", SiGetPoint(server));
8978                PackAddInt(p, "Weight", server->Weight);
8979
8980                // ホスト名
8981                GetMachineName(tmp, sizeof(tmp));
8982                PackAddStr(p, "HostName", tmp);
8983
8984                // 公開 IP
8985                PackAddIp32(p, "PublicIp", server->PublicIp);
8986
8987                // 公開ポート
8988                for (i = 0;i < server->NumPublicPort;i++)
8989                {
8990                    PackAddIntEx(p, "PublicPort", server->PublicPorts[i], i, server->NumPublicPort);
8991                }
8992
8993                ret = HttpClientSend(c->FirstSock, p);
8994
8995                if (ret)
8996                {
8997                    PACK *p;
8998                    UINT err = ERR_PROTOCOL_ERROR;
8999
9000                    first_failed = true;
9001                    p = HttpClientRecv(c->FirstSock);
9002                    if (p != NULL && (err = GetErrorFromPack(p)) == 0)
9003                    {
9004                        // 接続成功
9005                        SLog(server->Cedar, "LS_FARM_START");
9006                        f->CurrentConnectedTime = SystemTime64();
9007                        if (f->FirstConnectedTime == 0)
9008                        {
9009                            f->FirstConnectedTime = SystemTime64();
9010                        }
9011                        f->NumConnected++;
9012                        Debug("Connect Succeed.\n");
9013                        f->Online = true;
9014
9015                        // メイン処理
9016                        SiAcceptTasksFromController(f, c->FirstSock);
9017
9018                        f->Online = false;
9019                    }
9020                    else
9021                    {
9022                        // エラー
9023                        f->LastError = err;
9024                        SLog(server->Cedar, "LS_FARM_CONNECT_2", server->ControllerName,
9025                            GetUniErrorStr(err), err);
9026                    }
9027                    FreePack(p);
9028                }
9029                else
9030                {
9031                    f->LastError = ERR_DISCONNECTED;
9032
9033                    if (first_failed)
9034                    {
9035                        SLog(server->Cedar, "LS_FARM_CONNECT_3", server->ControllerName, RETRY_CONNECT_TO_CONTROLLER_INTERVAL / 1000);
9036                        first_failed = false;
9037                    }
9038                }
9039            }
9040
9041            FreePack(p);
9042
9043            // 接続切断
9044            Lock(f->lock);
9045            {
9046                if (f->Sock != NULL)
9047                {
9048                    ReleaseSock(f->Sock);
9049                    f->Sock = NULL;
9050                }
9051            }
9052            Unlock(f->lock);
9053
9054            ReleaseSession(s);
9055            s = NULL;
9056
9057            if (f->LastError == ERR_TRYING_TO_CONNECT)
9058            {
9059                f->LastError = ERR_DISCONNECTED;
9060            }
9061        }
9062        else
9063        {
9064            // 接続失敗
9065            f->LastError = ERR_CONNECT_TO_FARM_CONTROLLER;
9066
9067            if (first_failed)
9068            {
9069                SLog(server->Cedar, "LS_FARM_CONNECT_3", server->ControllerName, RETRY_CONNECT_TO_CONTROLLER_INTERVAL / 1000);
9070                first_failed = false;
9071            }
9072        }
9073
9074        Debug("Controller Disconnected. ERROR = %S\n", _E(f->LastError));
9075
9076        f->NumFailed = f->NumTry - f->NumConnected;
9077
9078        // イベント待機
9079        Wait(f->HaltEvent, RETRY_CONNECT_TO_CONTROLLER_INTERVAL);
9080
9081        if (f->Halt)
9082        {
9083            // 停止フラグ
9084            break;
9085        }
9086    }
9087
9088    SLog(server->Cedar, "LS_FARM_DISCONNECT");
9089}
9090
9091// コントローラへの接続を切断
9092void SiStopConnectToController(FARM_CONTROLLER *f)
9093{
9094    // 引数チェック
9095    if (f == NULL)
9096    {
9097        return;
9098    }
9099
9100    f->Halt = true;
9101
9102    // 接続を停止
9103    Lock(f->lock);
9104    {
9105        Disconnect(f->Sock);
9106    }
9107    Unlock(f->lock);
9108
9109    Set(f->HaltEvent);
9110
9111    // スレッド停止を待機
9112    WaitThread(f->Thread, INFINITE);
9113    ReleaseThread(f->Thread);
9114
9115    DeleteLock(f->lock);
9116    ReleaseEvent(f->HaltEvent);
9117
9118    Free(f);
9119}
9120
9121// コントローラへの接続の開始
9122FARM_CONTROLLER *SiStartConnectToController(SERVER *s)
9123{
9124    FARM_CONTROLLER *f;
9125    THREAD *t;
9126    // 引数チェック
9127    if (s == NULL)
9128    {
9129        return NULL;
9130    }
9131
9132    f = ZeroMalloc(sizeof(FARM_CONTROLLER));
9133    f->Server = s;
9134    f->LastError = ERR_TRYING_TO_CONNECT;
9135    f->HaltEvent = NewEvent();
9136    f->lock = NewLock();
9137
9138    t = NewThread(SiConnectToControllerThread, f);
9139    WaitThreadInit(t);
9140    ReleaseThread(t);
9141
9142    return f;
9143}
9144
9145// サーバーの作成
9146SERVER *SiNewServer(bool bridge)
9147{
9148    SERVER *s;
9149
9150    s = ZeroMalloc(sizeof(SERVER));
9151
9152    SiInitHubCreateHistory(s);
9153
9154    InitServerCapsCache(s);
9155
9156    Rand(s->MyRandomKey, sizeof(s->MyRandomKey));
9157
9158    s->lock = NewLock();
9159    s->SaveCfgLock = NewLock();
9160    s->ref = NewRef();
9161    s->Cedar = NewCedar(NULL, NULL);
9162    s->Cedar->Server = s;
9163    s->Cedar->CheckExpires = true;
9164    s->ServerListenerList = NewList(CompareServerListener);
9165    s->StartTime = SystemTime64();
9166    s->TasksFromFarmControllerLock = NewLock();
9167
9168    if (bridge)
9169    {
9170        SetCedarVpnBridge(s->Cedar);
9171    }
9172
9173#ifdef OS_WIN32
9174    if (IsHamMode() == false)
9175    {
9176        RegistWindowsFirewallAll();
9177    }
9178#endif
9179
9180    s->Keep = StartKeep();
9181
9182    // ログ関係
9183    MakeDir(bridge == false ? SERVER_LOG_DIR_NAME : BRIDGE_LOG_DIR_NAME);
9184    s->Logger = NewLog(bridge == false ? SERVER_LOG_DIR_NAME : BRIDGE_LOG_DIR_NAME, SERVER_LOG_PERFIX, LOG_SWITCH_DAY);
9185
9186    SLog(s->Cedar, "L_LINE");
9187    SLog(s->Cedar, "LS_START_2", s->Cedar->ServerStr, s->Cedar->VerString);
9188    SLog(s->Cedar, "LS_START_3", s->Cedar->BuildInfo);
9189    SLog(s->Cedar, "LS_START_UTF8");
9190    SLog(s->Cedar, "LS_START_1");
9191
9192    if (s->Cedar->Bridge == false)
9193    {
9194        s->LicenseSystem = LiNewLicenseSystem();
9195    }
9196
9197    // コンフィグレーション初期化
9198    SiInitConfiguration(s);
9199
9200    // 優先順位を上げる
9201    if (s->NoHighPriorityProcess == false)
9202    {
9203        OSSetHighPriority();
9204    }
9205
9206    if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
9207    {
9208        // コントローラへの接続を開始する
9209        s->FarmController = SiStartConnectToController(s);
9210    }
9211    else if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
9212    {
9213        FARM_MEMBER *f;
9214        // コントローラとしての動作を開始する
9215        s->FarmMemberList = NewList(NULL);
9216
9217        f = ZeroMalloc(sizeof(FARM_MEMBER));
9218        f->Cedar = s->Cedar;
9219        GetMachineName(f->hostname, sizeof(f->hostname));
9220        f->Me = true;
9221        f->HubList = NewList(CompareHubList);
9222        f->Weight = s->Weight;
9223
9224        s->Me = f;
9225
9226        Add(s->FarmMemberList, f);
9227
9228        SiStartFarmControl(s);
9229
9230        s->FarmControllerInited = true;
9231    }
9232
9233    InitServerSnapshot(s);
9234
9235    SiInitDeadLockCheck(s);
9236
9237    return s;
9238}
9239
Note: See TracBrowser for help on using the repository browser.