* tar xzf utvpn-src-unix-v101-7101-public-2010.06.27.tar.gz
[lab.git] / utvpn / utvpn-unix-v101-7101-public / src / Cedar / Admin.c
diff --git a/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Admin.c b/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Admin.c
new file mode 100644 (file)
index 0000000..50e8a14
--- /dev/null
@@ -0,0 +1,12320 @@
+// SoftEther UT-VPN SourceCode\r
+// \r
+// Copyright (C) 2004-2010 SoftEther Corporation.\r
+// Copyright (C) 2004-2010 University of Tsukuba, Japan.\r
+// Copyright (C) 2003-2010 Daiyuu Nobori.\r
+// All Rights Reserved.\r
+// \r
+// http://utvpn.tsukuba.ac.jp/\r
+// \r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// version 2 as published by the Free Software Foundation.\r
+// \r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+// GNU General Public License for more details.\r
+// \r
+// You should have received a copy of the GNU General Public License version 2\r
+// along with this program; if not, write to the Free Software\r
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
+// \r
+// このファイルは GPL バージョン 2 ライセンスで公開されています。\r
+// 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
+// することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
+// を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
+// 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
+// \r
+// この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の\r
+// ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )\r
+// および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって\r
+// ホストされています。\r
+// 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
+// および、試験または研究のために利用が行われることを想定して配布\r
+// しています。\r
+// SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
+// あります。\r
+// 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
+// の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
+// いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
+// ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
+// に組み込みさせていただきます。\r
+// \r
+// GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
+// 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
+// \r
+// 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
+// (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
+// ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
+// 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
+// ください。\r
+// \r
+// お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
+// セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
+// UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
+// 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
+// および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
+// 公益保護にご協力いただきますようお願い申し上げます。\r
+// \r
+// ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
+// 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
+// を保護するための努力を行います。\r
+// \r
+// ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
+// 日本国内の脆弱性情報届出受付公的機関:\r
+//         独立行政法人 情報処理推進機構\r
+//         http://www.ipa.go.jp/security/vuln/report/\r
+// \r
+// 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
+// 連絡先: http://www.softether.co.jp/jp/contact/\r
+\r
+// -----------------------------------------------\r
+// [ChangeLog]\r
+// 2010.05.20\r
+//  新規リリース by SoftEther\r
+// -----------------------------------------------\r
+\r
+// Admin.c\r
+// 管理用 RPC モジュール\r
+\r
+#include "CedarPch.h"\r
+\r
+// RPC 関数関係マクロ\r
+// このあたりは急いで実装したのでコードがあまり美しくない。\r
+// 本当は Sun RPC のプリプロセッサのようにきれいな処理方法を採用したがったが\r
+// とりあえず今はマクロの羅列になっている。\r
+#define        DECLARE_RPC_EX(rpc_name, data_type, function, in_rpc, out_rpc, free_rpc)                \\r
+       else if (StrCmpi(name, rpc_name) == 0)                                                          \\r
+       {                                                                                                                                       \\r
+               data_type *t;                                                                                                   \\r
+               t = ZeroMalloc(sizeof(data_type));                                                              \\r
+               in_rpc(t, p);                                                                                                   \\r
+               err = function(a, t);                                                                                   \\r
+               if (err == ERR_NO_ERROR)                                                                                \\r
+               {                                                                                                                               \\r
+                       out_rpc(ret, t);                                                                                        \\r
+               }                                                                                                                               \\r
+               free_rpc(t);                                                                                                    \\r
+               Free(t);                                                                                                                \\r
+               ok = true;                                                                                                              \\r
+       }\r
+#define        DECLARE_RPC(rpc_name, data_type, function, in_rpc, out_rpc)             \\r
+       else if (StrCmpi(name, rpc_name) == 0)                                                          \\r
+       {                                                                                                                                       \\r
+               data_type *t;                                                                                                   \\r
+               t = ZeroMalloc(sizeof(data_type));                                                              \\r
+               in_rpc(t, p);                                                                                                   \\r
+               err = function(a, t);                                                                                   \\r
+               if (err == ERR_NO_ERROR)                                                                                \\r
+               {                                                                                                                               \\r
+                       out_rpc(ret, t);                                                                                        \\r
+               }                                                                                                                               \\r
+               Free(t);                                                                                                                \\r
+               ok = true;                                                                                                              \\r
+       }\r
+#define        DECLARE_SC_EX(rpc_name, data_type, function, in_rpc, out_rpc, free_rpc) \\r
+       UINT function(RPC *r, data_type *t)                                                                     \\r
+       {                                                                                                                                       \\r
+               PACK *p, *ret;                                                                                                  \\r
+               UINT err;                                                                                                               \\r
+               if (r == NULL || t == NULL)                                                                             \\r
+               {                                                                                                                               \\r
+                       return ERR_INTERNAL_ERROR;                                                                      \\r
+               }                                                                                                                               \\r
+               p = NewPack();                                                                                                  \\r
+               out_rpc(p, t);                                                                                                  \\r
+               free_rpc(t);                                                                                                    \\r
+               Zero(t, sizeof(data_type));                                                                             \\r
+               ret = AdminCall(r, rpc_name, p);                                                                \\r
+               err = GetErrorFromPack(ret);                                                                    \\r
+               if (err == ERR_NO_ERROR)                                                                                \\r
+               {                                                                                                                               \\r
+                       in_rpc(t, ret);                                                                                         \\r
+               }                                                                                                                               \\r
+               FreePack(ret);                                                                                                  \\r
+               return err;                                                                                                             \\r
+       }\r
+#define        DECLARE_SC(rpc_name, data_type, function, in_rpc, out_rpc)              \\r
+       UINT function(RPC *r, data_type *t)                                                                     \\r
+       {                                                                                                                                       \\r
+               PACK *p, *ret;                                                                                                  \\r
+               UINT err;                                                                                                               \\r
+               if (r == NULL || t == NULL)                                                                             \\r
+               {                                                                                                                               \\r
+                       return ERR_INTERNAL_ERROR;                                                                      \\r
+               }                                                                                                                               \\r
+               p = NewPack();                                                                                                  \\r
+               out_rpc(p, t);                                                                                                  \\r
+               ret = AdminCall(r, rpc_name, p);                                                                \\r
+               err = GetErrorFromPack(ret);                                                                    \\r
+               if (err == ERR_NO_ERROR)                                                                                \\r
+               {                                                                                                                               \\r
+                       in_rpc(t, ret);                                                                                         \\r
+               }                                                                                                                               \\r
+               FreePack(ret);                                                                                                  \\r
+               return err;                                                                                                             \\r
+       }\r
+#define        CHECK_RIGHT                                                                                                             \\r
+       if (a->ServerAdmin == false && (t->HubName == NULL || StrCmpi(a->HubName, t->HubName) != 0))    \\r
+               return ERR_NOT_ENOUGH_RIGHT;    \\r
+       if (IsEmptyStr(t->HubName))                     \\r
+               return ERR_INVALID_PARAMETER;\r
+#define        SERVER_ADMIN_ONLY                                                                                               \\r
+       if (a->ServerAdmin == false)                                                                            \\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+#define        NO_SUPPORT_FOR_BRIDGE                                                                                   \\r
+       if (a->Server->Cedar->Bridge)                                                                           \\r
+               return ERR_NOT_SUPPORTED;\r
+\r
+// サーバーの Caps を取得 (取得できない場合はビルド番号から判別)\r
+CAPSLIST *ScGetCapsEx(RPC *rpc)\r
+{\r
+       RPC_SERVER_INFO info;\r
+       CAPSLIST *t;\r
+       bool is_bridge = false;\r
+       // 引数チェック\r
+       if (rpc == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       Zero(&info, sizeof(info));\r
+       ScGetServerInfo(rpc, &info);\r
+\r
+       t = ZeroMalloc(sizeof(CAPSLIST));\r
+\r
+       // RPC で Caps を取得してみる\r
+       if (ScGetCaps(rpc, t) != ERR_NO_ERROR)\r
+       {\r
+               UINT build;\r
+\r
+               Free(t);\r
+               t = NewCapsList();\r
+\r
+               // 取得に失敗したのでビルド番号を取得する\r
+               // (ものすごく古いバージョンの VPN Server のための対応コード)\r
+               build = info.ServerBuildInt;\r
+\r
+               is_bridge = (SearchStrEx(info.ServerProductName, "bridge", 0, false) == INFINITE) ? false : true;\r
+\r
+               AddCapsInt(t, "i_max_packet_size", 1514);\r
+\r
+               if (is_bridge == false)\r
+               {\r
+                       AddCapsInt(t, "i_max_hubs", 4096);\r
+                       AddCapsInt(t, "i_max_sessions", 4096);\r
+\r
+                       if (info.ServerType != SERVER_TYPE_FARM_MEMBER)\r
+                       {\r
+                               AddCapsInt(t, "i_max_users_per_hub", 10000);\r
+                               AddCapsInt(t, "i_max_groups_per_hub", 10000);\r
+                               AddCapsInt(t, "i_max_access_lists", 4096);\r
+                       }\r
+                       else\r
+                       {\r
+                               AddCapsInt(t, "i_max_users_per_hub", 0);\r
+                               AddCapsInt(t, "i_max_groups_per_hub", 0);\r
+                               AddCapsInt(t, "i_max_access_lists", 0);\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       AddCapsInt(t, "i_max_hubs", 0);\r
+                       AddCapsInt(t, "i_max_sessions", 0);\r
+                       AddCapsInt(t, "i_max_users_per_hub", 0);\r
+                       AddCapsInt(t, "i_max_groups_per_hub", 0);\r
+                       AddCapsInt(t, "i_max_access_lists", 0);\r
+               }\r
+\r
+               AddCapsInt(t, "i_max_mac_tables", 10000);\r
+               AddCapsInt(t, "i_max_ip_tables", 10000);\r
+\r
+               if (info.ServerType == SERVER_TYPE_STANDALONE)\r
+               {\r
+                       AddCapsBool(t, "b_support_securenat", (build >= 3600) ? true : false);\r
+                       AddCapsInt(t, "i_max_secnat_tables", 4096);\r
+               }\r
+               else\r
+               {\r
+                       AddCapsBool(t, "b_support_securenat", false);\r
+                       AddCapsInt(t, "i_max_secnat_tables", 0);\r
+               }\r
+\r
+               if (is_bridge)\r
+               {\r
+                       AddCapsBool(t, "b_bridge", true);\r
+               }\r
+               else if (info.ServerType == SERVER_TYPE_STANDALONE)\r
+               {\r
+                       AddCapsBool(t, "b_standalone", true);\r
+               }\r
+               else if (info.ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+               {\r
+                       AddCapsBool(t, "b_cluster_controller", true);\r
+               }\r
+               else\r
+               {\r
+                       AddCapsBool(t, "b_cluster_member", true);\r
+               }\r
+\r
+               AddCapsBool(t, "b_support_config_hub", info.ServerType != SERVER_TYPE_FARM_MEMBER &&\r
+                       is_bridge == false);\r
+\r
+               AddCapsBool(t, "b_vpn_client_connect", is_bridge == false ? true : false);\r
+\r
+               AddCapsBool(t, "b_support_radius", info.ServerType != SERVER_TYPE_FARM_MEMBER &&\r
+                       is_bridge == false);\r
+\r
+               if (build >= 3600)\r
+               {\r
+                       RPC_BRIDGE_SUPPORT b;\r
+                       Zero(&b, sizeof(b));\r
+                       if (ScGetBridgeSupport(rpc, &b) == ERR_NO_ERROR)\r
+                       {\r
+                               AddCapsBool(t, "b_local_bridge", b.IsBridgeSupportedOs);\r
+                               AddCapsBool(t, "b_must_install_pcap", b.IsWinPcapNeeded);\r
+                       }\r
+                       else\r
+                       {\r
+                               AddCapsBool(t, "b_local_bridge", false);\r
+                               AddCapsBool(t, "b_must_install_pcap", false);\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       AddCapsBool(t, "b_local_bridge", false);\r
+                       AddCapsBool(t, "b_must_install_pcap", false);\r
+               }\r
+\r
+               AddCapsBool(t, "b_tap_supported", false);\r
+\r
+               if (info.ServerType == SERVER_TYPE_STANDALONE)\r
+               {\r
+                       AddCapsBool(t, "b_support_cascade", true);\r
+               }\r
+               else\r
+               {\r
+                       AddCapsBool(t, "b_support_cascade", false);\r
+               }\r
+\r
+               AddCapsBool(t, "b_support_cascade_cert", false);\r
+               AddCapsBool(t, "b_support_config_log", info.ServerType != SERVER_TYPE_FARM_MEMBER);\r
+               AddCapsBool(t, "b_support_autodelete", false);\r
+       }\r
+       else\r
+       {\r
+               // 成功した場合\r
+               if (info.ServerBuildInt <= 4350)\r
+               {\r
+                       if (is_bridge == false)\r
+                       {\r
+                               // Build 4300 以下では必ず b_support_cluster が true\r
+                               CAPS *caps = GetCaps(t, "b_support_cluster");\r
+                               if (caps == NULL)\r
+                               {\r
+                                       AddCapsBool(t, "b_support_cluster", true);\r
+                               }\r
+                               else\r
+                               {\r
+                                       caps->Value = 1;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (true)\r
+       {\r
+               TOKEN_LIST *names;\r
+\r
+               // サーバー側に存在しない Caps の一覧を false として登録\r
+               names = GetTableNameStartWith("CT_b_");\r
+               if (names != NULL)\r
+               {\r
+                       UINT i;\r
+                       for (i = 0;i < names->NumTokens;i++)\r
+                       {\r
+                               char *name = names->Token[i] + 3;\r
+\r
+                               if (GetCaps(t, name) == NULL)\r
+                               {\r
+                                       AddCapsBool(t, name, false);\r
+                               }\r
+                       }\r
+\r
+                       FreeToken(names);\r
+               }\r
+       }\r
+\r
+       FreeRpcServerInfo(&info);\r
+\r
+       return t;\r
+}\r
+\r
+// 管理用 RPC 関数ディスパッチルーチン\r
+PACK *AdminDispatch(RPC *rpc, char *name, PACK *p)\r
+{\r
+       ADMIN *a;\r
+       PACK *ret;\r
+       UINT err;\r
+       SERVER *server = NULL;\r
+       CEDAR *cedar = NULL;\r
+       bool ok = false;\r
+       // 引数チェック\r
+       if (rpc == NULL || name == NULL || p == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       ret = NewPack();\r
+       err = ERR_NO_ERROR;\r
+\r
+       // 管理構造体\r
+       a = (ADMIN *)rpc->Param;\r
+       if (a == NULL)\r
+       {\r
+               FreePack(ret);\r
+               return NULL;\r
+       }\r
+\r
+       server = a->Server;\r
+\r
+       if (server != NULL)\r
+       {\r
+               cedar = server->Cedar;\r
+       }\r
+\r
+       Lock(cedar->CedarSuperLock);\r
+\r
+       if (true)\r
+       {\r
+               char tmp[MAX_PATH];\r
+               char ip[MAX_PATH];\r
+               UINT rpc_id = 0;\r
+\r
+               StrCpy(ip, sizeof(ip), "Unknown");\r
+\r
+               if (rpc->Sock != NULL)\r
+               {\r
+                       IPToStr(ip, sizeof(ip), &rpc->Sock->RemoteIP);\r
+                       rpc_id = rpc->Sock->socket;\r
+               }\r
+\r
+               Format(tmp, sizeof(tmp), "RPC: RPC-%u (%s): Entering RPC [%s]...",\r
+                       rpc_id, ip, name);\r
+\r
+               SiDebugLog(a->Server, tmp);\r
+       }\r
+\r
+       if (0) {}\r
+\r
+       // このあたりは急いで実装したのでコードがあまり美しくない。\r
+       // 本当は Sun RPC のプリプロセッサのようにきれいな処理方法を採用したがったが\r
+       // とりあえず今はマクロの羅列になっている。\r
+\r
+       // RPC 関数定義: ここから\r
+       DECLARE_RPC_EX("Test", RPC_TEST, StTest, InRpcTest, OutRpcTest, FreeRpcTest)\r
+       DECLARE_RPC_EX("GetServerInfo", RPC_SERVER_INFO, StGetServerInfo, InRpcServerInfo, OutRpcServerInfo, FreeRpcServerInfo)\r
+       DECLARE_RPC("GetServerStatus", RPC_SERVER_STATUS, StGetServerStatus, InRpcServerStatus, OutRpcServerStatus)\r
+       DECLARE_RPC("CreateListener", RPC_LISTENER, StCreateListener, InRpcListener, OutRpcListener)\r
+       DECLARE_RPC_EX("EnumListener", RPC_LISTENER_LIST, StEnumListener, InRpcListenerList, OutRpcListenerList, FreeRpcListenerList)\r
+       DECLARE_RPC("DeleteListener", RPC_LISTENER, StDeleteListener, InRpcListener, OutRpcListener)\r
+       DECLARE_RPC("EnableListener", RPC_LISTENER, StEnableListener, InRpcListener, OutRpcListener)\r
+       DECLARE_RPC("SetServerPassword", RPC_SET_PASSWORD, StSetServerPassword, InRpcSetPassword, OutRpcSetPassword)\r
+       DECLARE_RPC_EX("SetFarmSetting", RPC_FARM, StSetFarmSetting, InRpcFarm, OutRpcFarm, FreeRpcFarm)\r
+       DECLARE_RPC_EX("GetFarmSetting", RPC_FARM, StGetFarmSetting, InRpcFarm, OutRpcFarm, FreeRpcFarm)\r
+       DECLARE_RPC_EX("GetFarmInfo", RPC_FARM_INFO, StGetFarmInfo, InRpcFarmInfo, OutRpcFarmInfo, FreeRpcFarmInfo)\r
+       DECLARE_RPC_EX("EnumFarmMember", RPC_ENUM_FARM, StEnumFarmMember, InRpcEnumFarm, OutRpcEnumFarm, FreeRpcEnumFarm)\r
+       DECLARE_RPC("GetFarmConnectionStatus", RPC_FARM_CONNECTION_STATUS, StGetFarmConnectionStatus, InRpcFarmConnectionStatus, OutRpcFarmConnectionStatus)\r
+       DECLARE_RPC_EX("SetServerCert", RPC_KEY_PAIR, StSetServerCert, InRpcKeyPair, OutRpcKeyPair, FreeRpcKeyPair)\r
+       DECLARE_RPC_EX("GetServerCert", RPC_KEY_PAIR, StGetServerCert, InRpcKeyPair, OutRpcKeyPair, FreeRpcKeyPair)\r
+       DECLARE_RPC_EX("GetServerCipher", RPC_STR, StGetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)\r
+       DECLARE_RPC_EX("SetServerCipher", RPC_STR, StSetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)\r
+       DECLARE_RPC("CreateHub", RPC_CREATE_HUB, StCreateHub, InRpcCreateHub, OutRpcCreateHub)\r
+       DECLARE_RPC("SetHub", RPC_CREATE_HUB, StSetHub, InRpcCreateHub, OutRpcCreateHub)\r
+       DECLARE_RPC("GetHub", RPC_CREATE_HUB, StGetHub, InRpcCreateHub, OutRpcCreateHub)\r
+       DECLARE_RPC_EX("EnumHub", RPC_ENUM_HUB, StEnumHub, InRpcEnumHub, OutRpcEnumHub, FreeRpcEnumHub)\r
+       DECLARE_RPC("DeleteHub", RPC_DELETE_HUB, StDeleteHub, InRpcDeleteHub, OutRpcDeleteHub)\r
+       DECLARE_RPC("GetHubRadius", RPC_RADIUS, StGetHubRadius, InRpcRadius, OutRpcRadius)\r
+       DECLARE_RPC("SetHubRadius", RPC_RADIUS, StSetHubRadius, InRpcRadius, OutRpcRadius)\r
+       DECLARE_RPC_EX("EnumConnection", RPC_ENUM_CONNECTION, StEnumConnection, InRpcEnumConnection, OutRpcEnumConnection, FreeRpcEnumConnetion)\r
+       DECLARE_RPC("DisconnectConnection", RPC_DISCONNECT_CONNECTION, StDisconnectConnection, InRpcDisconnectConnection, OutRpcDisconnectConnection)\r
+       DECLARE_RPC("GetConnectionInfo", RPC_CONNECTION_INFO, StGetConnectionInfo, InRpcConnectionInfo, OutRpcConnectionInfo)\r
+       DECLARE_RPC("SetHubOnline", RPC_SET_HUB_ONLINE, StSetHubOnline, InRpcSetHubOnline, OutRpcSetHubOnline)\r
+       DECLARE_RPC("GetHubStatus", RPC_HUB_STATUS, StGetHubStatus, InRpcHubStatus, OutRpcHubStatus)\r
+       DECLARE_RPC("SetHubLog", RPC_HUB_LOG, StSetHubLog, InRpcHubLog, OutRpcHubLog)\r
+       DECLARE_RPC("GetHubLog", RPC_HUB_LOG, StGetHubLog, InRpcHubLog, OutRpcHubLog)\r
+       DECLARE_RPC_EX("AddCa", RPC_HUB_ADD_CA, StAddCa, InRpcHubAddCa, OutRpcHubAddCa, FreeRpcHubAddCa)\r
+       DECLARE_RPC_EX("EnumCa", RPC_HUB_ENUM_CA, StEnumCa, InRpcHubEnumCa, OutRpcHubEnumCa, FreeRpcHubEnumCa)\r
+       DECLARE_RPC_EX("GetCa", RPC_HUB_GET_CA, StGetCa, InRpcHubGetCa, OutRpcHubGetCa, FreeRpcHubGetCa)\r
+       DECLARE_RPC("DeleteCa", RPC_HUB_DELETE_CA, StDeleteCa, InRpcHubDeleteCa, OutRpcHubDeleteCa)\r
+       DECLARE_RPC("SetLinkOnline", RPC_LINK, StSetLinkOnline, InRpcLink, OutRpcLink)\r
+       DECLARE_RPC("SetLinkOffline", RPC_LINK, StSetLinkOffline, InRpcLink, OutRpcLink)\r
+       DECLARE_RPC("DeleteLink", RPC_LINK, StDeleteLink, InRpcLink, OutRpcLink)\r
+       DECLARE_RPC("RenameLink", RPC_RENAME_LINK, StRenameLink, InRpcRenameLink, OutRpcRenameLink)\r
+       DECLARE_RPC_EX("CreateLink", RPC_CREATE_LINK, StCreateLink, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)\r
+       DECLARE_RPC_EX("GetLink", RPC_CREATE_LINK, StGetLink, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)\r
+       DECLARE_RPC_EX("SetLink", RPC_CREATE_LINK, StSetLink, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)\r
+       DECLARE_RPC_EX("EnumLink", RPC_ENUM_LINK, StEnumLink, InRpcEnumLink, OutRpcEnumLink, FreeRpcEnumLink)\r
+       DECLARE_RPC_EX("GetLinkStatus", RPC_LINK_STATUS, StGetLinkStatus, InRpcLinkStatus, OutRpcLinkStatus, FreeRpcLinkStatus)\r
+       DECLARE_RPC("AddAccess", RPC_ADD_ACCESS, StAddAccess, InRpcAddAccess, OutRpcAddAccess)\r
+       DECLARE_RPC("DeleteAccess", RPC_DELETE_ACCESS, StDeleteAccess, InRpcDeleteAccess, OutRpcDeleteAccess)\r
+       DECLARE_RPC_EX("EnumAccess", RPC_ENUM_ACCESS_LIST, StEnumAccess, InRpcEnumAccessList, OutRpcEnumAccessList, FreeRpcEnumAccessList)\r
+       DECLARE_RPC_EX("SetAccessList", RPC_ENUM_ACCESS_LIST, StSetAccessList, InRpcEnumAccessList, OutRpcEnumAccessList, FreeRpcEnumAccessList)\r
+       DECLARE_RPC_EX("CreateUser", RPC_SET_USER, StCreateUser, InRpcSetUser, OutRpcSetUser, FreeRpcSetUser)\r
+       DECLARE_RPC_EX("SetUser", RPC_SET_USER, StSetUser, InRpcSetUser, OutRpcSetUser, FreeRpcSetUser)\r
+       DECLARE_RPC_EX("GetUser", RPC_SET_USER, StGetUser, InRpcSetUser, OutRpcSetUser, FreeRpcSetUser)\r
+       DECLARE_RPC("DeleteUser", RPC_DELETE_USER, StDeleteUser, InRpcDeleteUser, OutRpcDeleteUser)\r
+       DECLARE_RPC_EX("EnumUser", RPC_ENUM_USER, StEnumUser, InRpcEnumUser, OutRpcEnumUser, FreeRpcEnumUser)\r
+       DECLARE_RPC_EX("CreateGroup", RPC_SET_GROUP, StCreateGroup, InRpcSetGroup, OutRpcSetGroup, FreeRpcSetGroup)\r
+       DECLARE_RPC_EX("SetGroup", RPC_SET_GROUP, StSetGroup, InRpcSetGroup, OutRpcSetGroup, FreeRpcSetGroup)\r
+       DECLARE_RPC_EX("GetGroup", RPC_SET_GROUP, StGetGroup, InRpcSetGroup, OutRpcSetGroup, FreeRpcSetGroup)\r
+       DECLARE_RPC("DeleteGroup", RPC_DELETE_USER, StDeleteGroup, InRpcDeleteUser, OutRpcDeleteUser)\r
+       DECLARE_RPC_EX("EnumGroup", RPC_ENUM_GROUP, StEnumGroup, InRpcEnumGroup, OutRpcEnumGroup, FreeRpcEnumGroup)\r
+       DECLARE_RPC_EX("EnumSession", RPC_ENUM_SESSION, StEnumSession, InRpcEnumSession, OutRpcEnumSession, FreeRpcEnumSession)\r
+       DECLARE_RPC_EX("GetSessionStatus", RPC_SESSION_STATUS, StGetSessionStatus, InRpcSessionStatus, OutRpcSessionStatus, FreeRpcSessionStatus)\r
+       DECLARE_RPC("DeleteSession", RPC_DELETE_SESSION, StDeleteSession, InRpcDeleteSession, OutRpcDeleteSession)\r
+       DECLARE_RPC_EX("EnumMacTable", RPC_ENUM_MAC_TABLE, StEnumMacTable, InRpcEnumMacTable, OutRpcEnumMacTable, FreeRpcEnumMacTable)\r
+       DECLARE_RPC("DeleteMacTable", RPC_DELETE_TABLE, StDeleteMacTable, InRpcDeleteTable, OutRpcDeleteTable)\r
+       DECLARE_RPC_EX("EnumIpTable", RPC_ENUM_IP_TABLE, StEnumIpTable, InRpcEnumIpTable, OutRpcEnumIpTable, FreeRpcEnumIpTable)\r
+       DECLARE_RPC("DeleteIpTable", RPC_DELETE_TABLE, StDeleteIpTable, InRpcDeleteTable, OutRpcDeleteTable)\r
+       DECLARE_RPC("SetKeep", RPC_KEEP, StSetKeep, InRpcKeep, OutRpcKeep)\r
+       DECLARE_RPC("GetKeep", RPC_KEEP, StGetKeep, InRpcKeep, OutRpcKeep)\r
+       DECLARE_RPC("EnableSecureNAT", RPC_HUB, StEnableSecureNAT, InRpcHub, OutRpcHub)\r
+       DECLARE_RPC("DisableSecureNAT", RPC_HUB, StDisableSecureNAT, InRpcHub, OutRpcHub)\r
+       DECLARE_RPC("SetSecureNATOption", VH_OPTION, StSetSecureNATOption, InVhOption, OutVhOption)\r
+       DECLARE_RPC("GetSecureNATOption", VH_OPTION, StGetSecureNATOption, InVhOption, OutVhOption)\r
+       DECLARE_RPC_EX("EnumNAT", RPC_ENUM_NAT, StEnumNAT, InRpcEnumNat, OutRpcEnumNat, FreeRpcEnumNat)\r
+       DECLARE_RPC_EX("EnumDHCP", RPC_ENUM_DHCP, StEnumDHCP, InRpcEnumDhcp, OutRpcEnumDhcp, FreeRpcEnumDhcp)\r
+       DECLARE_RPC("GetSecureNATStatus", RPC_NAT_STATUS, StGetSecureNATStatus, InRpcNatStatus, OutRpcNatStatus)\r
+       DECLARE_RPC_EX("EnumEthernet", RPC_ENUM_ETH, StEnumEthernet, InRpcEnumEth, OutRpcEnumEth, FreeRpcEnumEth)\r
+       DECLARE_RPC("AddLocalBridge", RPC_LOCALBRIDGE, StAddLocalBridge, InRpcLocalBridge, OutRpcLocalBridge)\r
+       DECLARE_RPC("DeleteLocalBridge", RPC_LOCALBRIDGE, StDeleteLocalBridge, InRpcLocalBridge, OutRpcLocalBridge)\r
+       DECLARE_RPC_EX("EnumLocalBridge", RPC_ENUM_LOCALBRIDGE, StEnumLocalBridge, InRpcEnumLocalBridge, OutRpcEnumLocalBridge, FreeRpcEnumLocalBridge)\r
+       DECLARE_RPC("GetBridgeSupport", RPC_BRIDGE_SUPPORT, StGetBridgeSupport, InRpcBridgeSupport, OutRpcBridgeSupport)\r
+       DECLARE_RPC("RebootServer", RPC_TEST, StRebootServer, InRpcTest, OutRpcTest)\r
+       DECLARE_RPC_EX("GetCaps", CAPSLIST, StGetCaps, InRpcCapsList, OutRpcCapsList, FreeRpcCapsList)\r
+       DECLARE_RPC_EX("GetConfig", RPC_CONFIG, StGetConfig, InRpcConfig, OutRpcConfig, FreeRpcConfig)\r
+       DECLARE_RPC_EX("SetConfig", RPC_CONFIG, StSetConfig, InRpcConfig, OutRpcConfig, FreeRpcConfig)\r
+       DECLARE_RPC_EX("GetDefaultHubAdminOptions", RPC_ADMIN_OPTION, StGetDefaultHubAdminOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)\r
+       DECLARE_RPC_EX("GetHubAdminOptions", RPC_ADMIN_OPTION, StGetHubAdminOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)\r
+       DECLARE_RPC_EX("SetHubAdminOptions", RPC_ADMIN_OPTION, StSetHubAdminOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)\r
+       DECLARE_RPC_EX("GetHubExtOptions", RPC_ADMIN_OPTION, StGetHubExtOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)\r
+       DECLARE_RPC_EX("SetHubExtOptions", RPC_ADMIN_OPTION, StSetHubExtOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)\r
+       DECLARE_RPC("AddL3Switch", RPC_L3SW, StAddL3Switch, InRpcL3Sw, OutRpcL3Sw)\r
+       DECLARE_RPC("DelL3Switch", RPC_L3SW, StDelL3Switch, InRpcL3Sw, OutRpcL3Sw)\r
+       DECLARE_RPC_EX("EnumL3Switch", RPC_ENUM_L3SW, StEnumL3Switch, InRpcEnumL3Sw, OutRpcEnumL3Sw, FreeRpcEnumL3Sw)\r
+       DECLARE_RPC("StartL3Switch", RPC_L3SW, StStartL3Switch, InRpcL3Sw, OutRpcL3Sw)\r
+       DECLARE_RPC("StopL3Switch", RPC_L3SW, StStopL3Switch, InRpcL3Sw, OutRpcL3Sw)\r
+       DECLARE_RPC("AddL3If", RPC_L3IF, StAddL3If, InRpcL3If, OutRpcL3If)\r
+       DECLARE_RPC("DelL3If", RPC_L3IF, StDelL3If, InRpcL3If, OutRpcL3If)\r
+       DECLARE_RPC_EX("EnumL3If", RPC_ENUM_L3IF, StEnumL3If, InRpcEnumL3If, OutRpcEnumL3If, FreeRpcEnumL3If)\r
+       DECLARE_RPC("AddL3Table", RPC_L3TABLE, StAddL3Table, InRpcL3Table, OutRpcL3Table)\r
+       DECLARE_RPC("DelL3Table", RPC_L3TABLE, StDelL3Table, InRpcL3Table, OutRpcL3Table)\r
+       DECLARE_RPC_EX("EnumL3Table", RPC_ENUM_L3TABLE, StEnumL3Table, InRpcEnumL3Table, OutRpcEnumL3Table, FreeRpcEnumL3Table)\r
+       DECLARE_RPC_EX("EnumCrl", RPC_ENUM_CRL, StEnumCrl, InRpcEnumCrl, OutRpcEnumCrl, FreeRpcEnumCrl)\r
+       DECLARE_RPC_EX("AddCrl", RPC_CRL, StAddCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)\r
+       DECLARE_RPC_EX("DelCrl", RPC_CRL, StDelCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)\r
+       DECLARE_RPC_EX("GetCrl", RPC_CRL, StGetCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)\r
+       DECLARE_RPC_EX("SetCrl", RPC_CRL, StSetCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)\r
+       DECLARE_RPC_EX("SetAcList", RPC_AC_LIST, StSetAcList, InRpcAcList, OutRpcAcList, FreeRpcAcList)\r
+       DECLARE_RPC_EX("GetAcList", RPC_AC_LIST, StGetAcList, InRpcAcList, OutRpcAcList, FreeRpcAcList)\r
+       DECLARE_RPC_EX("EnumLogFile", RPC_ENUM_LOG_FILE, StEnumLogFile, InRpcEnumLogFile, OutRpcEnumLogFile, FreeRpcEnumLogFile)\r
+       DECLARE_RPC_EX("ReadLogFile", RPC_READ_LOG_FILE, StReadLogFile, InRpcReadLogFile, OutRpcReadLogFile, FreeRpcReadLogFile)\r
+       DECLARE_RPC("AddLicenseKey", RPC_TEST, StAddLicenseKey, InRpcTest, OutRpcTest)\r
+       DECLARE_RPC("DelLicenseKey", RPC_TEST, StDelLicenseKey, InRpcTest, OutRpcTest)\r
+       DECLARE_RPC_EX("EnumLicenseKey", RPC_ENUM_LICENSE_KEY, StEnumLicenseKey, InRpcEnumLicenseKey, OutRpcEnumLicenseKey, FreeRpcEnumLicenseKey)\r
+       DECLARE_RPC("GetLicenseStatus", RPC_LICENSE_STATUS, StGetLicenseStatus, InRpcLicenseStatus, OutRpcLicenseStatus)\r
+       DECLARE_RPC("SetSysLog", SYSLOG_SETTING, StSetSysLog, InRpcSysLogSetting, OutRpcSysLogSetting)\r
+       DECLARE_RPC("GetSysLog", SYSLOG_SETTING, StGetSysLog, InRpcSysLogSetting, OutRpcSysLogSetting)\r
+       DECLARE_RPC_EX("EnumEthVLan", RPC_ENUM_ETH_VLAN, StEnumEthVLan, InRpcEnumEthVLan, OutRpcEnumEthVLan, FreeRpcEnumEthVLan)\r
+       DECLARE_RPC("SetEnableEthVLan", RPC_TEST, StSetEnableEthVLan, InRpcTest, OutRpcTest)\r
+       DECLARE_RPC_EX("SetHubMsg", RPC_MSG, StSetHubMsg, InRpcMsg, OutRpcMsg, FreeRpcMsg)\r
+       DECLARE_RPC_EX("GetHubMsg", RPC_MSG, StGetHubMsg, InRpcMsg, OutRpcMsg, FreeRpcMsg)\r
+       DECLARE_RPC("Crash", RPC_TEST, StCrash, InRpcTest, OutRpcTest)\r
+       DECLARE_RPC_EX("GetAdminMsg", RPC_MSG, StGetAdminMsg, InRpcMsg, OutRpcMsg, FreeRpcMsg)\r
+       DECLARE_RPC("Flush", RPC_TEST, StFlush, InRpcTest, OutRpcTest)\r
+       DECLARE_RPC("Debug", RPC_TEST, StDebug, InRpcTest, OutRpcTest)\r
+       // RPC 関数定義: ここまで\r
+\r
+       if (ok == false)\r
+       {\r
+               err = ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       if (err != ERR_NO_ERROR)\r
+       {\r
+               PackAddInt(ret, "error", err);\r
+       }\r
+\r
+       if (true)\r
+       {\r
+               char tmp[MAX_PATH];\r
+               char ip[MAX_PATH];\r
+               UINT rpc_id = 0;\r
+\r
+               StrCpy(ip, sizeof(ip), "Unknown");\r
+\r
+               if (rpc->Sock != NULL)\r
+               {\r
+                       IPToStr(ip, sizeof(ip), &rpc->Sock->RemoteIP);\r
+                       rpc_id = rpc->Sock->socket;\r
+               }\r
+\r
+               Format(tmp, sizeof(tmp), "RPC: RPC-%u (%s): Leaving RPC [%s] (Error: %u).",\r
+                       rpc_id, ip, name, err);\r
+\r
+               SiDebugLog(a->Server, tmp);\r
+       }\r
+\r
+       Unlock(cedar->CedarSuperLock);\r
+\r
+       return ret;\r
+}\r
+\r
+// このあたりは急いで実装したのでコードがあまり美しくない。\r
+// 本当は Sun RPC のプリプロセッサのようにきれいな処理方法を採用したがったが\r
+// とりあえず今はマクロの羅列になっている。\r
+\r
+// RPC 呼び出し関数定義: ここから\r
+DECLARE_SC_EX("Test", RPC_TEST, ScTest, InRpcTest, OutRpcTest, FreeRpcTest)\r
+DECLARE_SC_EX("GetServerInfo", RPC_SERVER_INFO, ScGetServerInfo, InRpcServerInfo, OutRpcServerInfo, FreeRpcServerInfo)\r
+DECLARE_SC("GetServerStatus", RPC_SERVER_STATUS, ScGetServerStatus, InRpcServerStatus, OutRpcServerStatus)\r
+DECLARE_SC("CreateListener", RPC_LISTENER, ScCreateListener, InRpcListener, OutRpcListener)\r
+DECLARE_SC_EX("EnumListener", RPC_LISTENER_LIST, ScEnumListener, InRpcListenerList, OutRpcListenerList, FreeRpcListenerList)\r
+DECLARE_SC("DeleteListener", RPC_LISTENER, ScDeleteListener, InRpcListener, OutRpcListener)\r
+DECLARE_SC("EnableListener", RPC_LISTENER, ScEnableListener, InRpcListener, OutRpcListener)\r
+DECLARE_SC("SetServerPassword", RPC_SET_PASSWORD, ScSetServerPassword, InRpcSetPassword, OutRpcSetPassword)\r
+DECLARE_SC_EX("SetFarmSetting", RPC_FARM, ScSetFarmSetting, InRpcFarm, OutRpcFarm, FreeRpcFarm)\r
+DECLARE_SC_EX("GetFarmSetting", RPC_FARM, ScGetFarmSetting, InRpcFarm, OutRpcFarm, FreeRpcFarm)\r
+DECLARE_SC_EX("GetFarmInfo", RPC_FARM_INFO, ScGetFarmInfo, InRpcFarmInfo, OutRpcFarmInfo, FreeRpcFarmInfo)\r
+DECLARE_SC_EX("EnumFarmMember", RPC_ENUM_FARM, ScEnumFarmMember, InRpcEnumFarm, OutRpcEnumFarm, FreeRpcEnumFarm)\r
+DECLARE_SC("GetFarmConnectionStatus", RPC_FARM_CONNECTION_STATUS, ScGetFarmConnectionStatus, InRpcFarmConnectionStatus, OutRpcFarmConnectionStatus)\r
+DECLARE_SC_EX("SetServerCert", RPC_KEY_PAIR, ScSetServerCert, InRpcKeyPair, OutRpcKeyPair, FreeRpcKeyPair)\r
+DECLARE_SC_EX("GetServerCert", RPC_KEY_PAIR, ScGetServerCert, InRpcKeyPair, OutRpcKeyPair, FreeRpcKeyPair)\r
+DECLARE_SC_EX("GetServerCipher", RPC_STR, ScGetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)\r
+DECLARE_SC_EX("SetServerCipher", RPC_STR, ScSetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)\r
+DECLARE_SC("CreateHub", RPC_CREATE_HUB, ScCreateHub, InRpcCreateHub, OutRpcCreateHub)\r
+DECLARE_SC("SetHub", RPC_CREATE_HUB, ScSetHub, InRpcCreateHub, OutRpcCreateHub)\r
+DECLARE_SC("GetHub", RPC_CREATE_HUB, ScGetHub, InRpcCreateHub, OutRpcCreateHub)\r
+DECLARE_SC_EX("EnumHub", RPC_ENUM_HUB, ScEnumHub, InRpcEnumHub, OutRpcEnumHub, FreeRpcEnumHub)\r
+DECLARE_SC("DeleteHub", RPC_DELETE_HUB, ScDeleteHub, InRpcDeleteHub, OutRpcDeleteHub)\r
+DECLARE_SC("GetHubRadius", RPC_RADIUS, ScGetHubRadius, InRpcRadius, OutRpcRadius)\r
+DECLARE_SC("SetHubRadius", RPC_RADIUS, ScSetHubRadius, InRpcRadius, OutRpcRadius)\r
+DECLARE_SC_EX("EnumConnection", RPC_ENUM_CONNECTION, ScEnumConnection, InRpcEnumConnection, OutRpcEnumConnection, FreeRpcEnumConnetion)\r
+DECLARE_SC("DisconnectConnection", RPC_DISCONNECT_CONNECTION, ScDisconnectConnection, InRpcDisconnectConnection, OutRpcDisconnectConnection)\r
+DECLARE_SC("GetConnectionInfo", RPC_CONNECTION_INFO, ScGetConnectionInfo, InRpcConnectionInfo, OutRpcConnectionInfo)\r
+DECLARE_SC("SetHubOnline", RPC_SET_HUB_ONLINE, ScSetHubOnline, InRpcSetHubOnline, OutRpcSetHubOnline)\r
+DECLARE_SC("GetHubStatus", RPC_HUB_STATUS, ScGetHubStatus, InRpcHubStatus, OutRpcHubStatus)\r
+DECLARE_SC("SetHubLog", RPC_HUB_LOG, ScSetHubLog, InRpcHubLog, OutRpcHubLog)\r
+DECLARE_SC("GetHubLog", RPC_HUB_LOG, ScGetHubLog, InRpcHubLog, OutRpcHubLog)\r
+DECLARE_SC_EX("AddCa", RPC_HUB_ADD_CA, ScAddCa, InRpcHubAddCa, OutRpcHubAddCa, FreeRpcHubAddCa)\r
+DECLARE_SC_EX("EnumCa", RPC_HUB_ENUM_CA, ScEnumCa, InRpcHubEnumCa, OutRpcHubEnumCa, FreeRpcHubEnumCa)\r
+DECLARE_SC_EX("GetCa", RPC_HUB_GET_CA, ScGetCa, InRpcHubGetCa, OutRpcHubGetCa, FreeRpcHubGetCa)\r
+DECLARE_SC("DeleteCa", RPC_HUB_DELETE_CA, ScDeleteCa, InRpcHubDeleteCa, OutRpcHubDeleteCa)\r
+DECLARE_SC_EX("CreateLink", RPC_CREATE_LINK, ScCreateLink, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)\r
+DECLARE_SC_EX("GetLink", RPC_CREATE_LINK, ScGetLink, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)\r
+DECLARE_SC_EX("SetLink", RPC_CREATE_LINK, ScSetLink, InRpcCreateLink, OutRpcCreateLink, FreeRpcCreateLink)\r
+DECLARE_SC_EX("EnumLink", RPC_ENUM_LINK, ScEnumLink, InRpcEnumLink, OutRpcEnumLink, FreeRpcEnumLink)\r
+DECLARE_SC_EX("GetLinkStatus", RPC_LINK_STATUS, ScGetLinkStatus, InRpcLinkStatus, OutRpcLinkStatus, FreeRpcLinkStatus)\r
+DECLARE_SC("SetLinkOnline", RPC_LINK, ScSetLinkOnline, InRpcLink, OutRpcLink)\r
+DECLARE_SC("SetLinkOffline", RPC_LINK, ScSetLinkOffline, InRpcLink, OutRpcLink)\r
+DECLARE_SC("DeleteLink", RPC_LINK, ScDeleteLink, InRpcLink, OutRpcLink)\r
+DECLARE_SC("RenameLink", RPC_RENAME_LINK, ScRenameLink, InRpcRenameLink, OutRpcRenameLink)\r
+DECLARE_SC("AddAccess", RPC_ADD_ACCESS, ScAddAccess, InRpcAddAccess, OutRpcAddAccess)\r
+DECLARE_SC("DeleteAccess", RPC_DELETE_ACCESS, ScDeleteAccess, InRpcDeleteAccess, OutRpcDeleteAccess)\r
+DECLARE_SC_EX("EnumAccess", RPC_ENUM_ACCESS_LIST, ScEnumAccess, InRpcEnumAccessList, OutRpcEnumAccessList, FreeRpcEnumAccessList)\r
+DECLARE_SC_EX("SetAccessList", RPC_ENUM_ACCESS_LIST, ScSetAccessList, InRpcEnumAccessList, OutRpcEnumAccessList, FreeRpcEnumAccessList)\r
+DECLARE_SC_EX("CreateUser", RPC_SET_USER, ScCreateUser, InRpcSetUser, OutRpcSetUser, FreeRpcSetUser)\r
+DECLARE_SC_EX("SetUser", RPC_SET_USER, ScSetUser, InRpcSetUser, OutRpcSetUser, FreeRpcSetUser)\r
+DECLARE_SC_EX("GetUser", RPC_SET_USER, ScGetUser, InRpcSetUser, OutRpcSetUser, FreeRpcSetUser)\r
+DECLARE_SC("DeleteUser", RPC_DELETE_USER, ScDeleteUser, InRpcDeleteUser, OutRpcDeleteUser)\r
+DECLARE_SC_EX("EnumUser", RPC_ENUM_USER, ScEnumUser, InRpcEnumUser, OutRpcEnumUser, FreeRpcEnumUser)\r
+DECLARE_SC_EX("CreateGroup", RPC_SET_GROUP, ScCreateGroup, InRpcSetGroup, OutRpcSetGroup, FreeRpcSetGroup)\r
+DECLARE_SC_EX("SetGroup", RPC_SET_GROUP, ScSetGroup, InRpcSetGroup, OutRpcSetGroup, FreeRpcSetGroup)\r
+DECLARE_SC_EX("GetGroup", RPC_SET_GROUP, ScGetGroup, InRpcSetGroup, OutRpcSetGroup, FreeRpcSetGroup)\r
+DECLARE_SC("DeleteGroup", RPC_DELETE_USER, ScDeleteGroup, InRpcDeleteUser, OutRpcDeleteUser)\r
+DECLARE_SC_EX("EnumGroup", RPC_ENUM_GROUP, ScEnumGroup, InRpcEnumGroup, OutRpcEnumGroup, FreeRpcEnumGroup)\r
+DECLARE_SC_EX("EnumSession", RPC_ENUM_SESSION, ScEnumSession, InRpcEnumSession, OutRpcEnumSession, FreeRpcEnumSession)\r
+DECLARE_SC_EX("GetSessionStatus", RPC_SESSION_STATUS, ScGetSessionStatus, InRpcSessionStatus, OutRpcSessionStatus, FreeRpcSessionStatus)\r
+DECLARE_SC("DeleteSession", RPC_DELETE_SESSION, ScDeleteSession, InRpcDeleteSession, OutRpcDeleteSession)\r
+DECLARE_SC_EX("EnumMacTable", RPC_ENUM_MAC_TABLE, ScEnumMacTable, InRpcEnumMacTable, OutRpcEnumMacTable, FreeRpcEnumMacTable)\r
+DECLARE_SC("DeleteMacTable", RPC_DELETE_TABLE, ScDeleteMacTable, InRpcDeleteTable, OutRpcDeleteTable)\r
+DECLARE_SC_EX("EnumIpTable", RPC_ENUM_IP_TABLE, ScEnumIpTable, InRpcEnumIpTable, OutRpcEnumIpTable, FreeRpcEnumIpTable)\r
+DECLARE_SC("DeleteIpTable", RPC_DELETE_TABLE, ScDeleteIpTable, InRpcDeleteTable, OutRpcDeleteTable)\r
+DECLARE_SC("SetKeep", RPC_KEEP, ScSetKeep, InRpcKeep, OutRpcKeep)\r
+DECLARE_SC("GetKeep", RPC_KEEP, ScGetKeep, InRpcKeep, OutRpcKeep)\r
+DECLARE_SC("EnableSecureNAT", RPC_HUB, ScEnableSecureNAT, InRpcHub, OutRpcHub)\r
+DECLARE_SC("DisableSecureNAT", RPC_HUB, ScDisableSecureNAT, InRpcHub, OutRpcHub)\r
+DECLARE_SC("SetSecureNATOption", VH_OPTION, ScSetSecureNATOption, InVhOption, OutVhOption)\r
+DECLARE_SC("GetSecureNATOption", VH_OPTION, ScGetSecureNATOption, InVhOption, OutVhOption)\r
+DECLARE_SC_EX("EnumNAT", RPC_ENUM_NAT, ScEnumNAT, InRpcEnumNat, OutRpcEnumNat, FreeRpcEnumNat)\r
+DECLARE_SC_EX("EnumDHCP", RPC_ENUM_DHCP, ScEnumDHCP, InRpcEnumDhcp, OutRpcEnumDhcp, FreeRpcEnumDhcp)\r
+DECLARE_SC("GetSecureNATStatus", RPC_NAT_STATUS, ScGetSecureNATStatus, InRpcNatStatus, OutRpcNatStatus)\r
+DECLARE_SC_EX("EnumEthernet", RPC_ENUM_ETH, ScEnumEthernet, InRpcEnumEth, OutRpcEnumEth, FreeRpcEnumEth)\r
+DECLARE_SC("AddLocalBridge", RPC_LOCALBRIDGE, ScAddLocalBridge, InRpcLocalBridge, OutRpcLocalBridge)\r
+DECLARE_SC("DeleteLocalBridge", RPC_LOCALBRIDGE, ScDeleteLocalBridge, InRpcLocalBridge, OutRpcLocalBridge)\r
+DECLARE_SC_EX("EnumLocalBridge", RPC_ENUM_LOCALBRIDGE, ScEnumLocalBridge, InRpcEnumLocalBridge, OutRpcEnumLocalBridge, FreeRpcEnumLocalBridge)\r
+DECLARE_SC("GetBridgeSupport", RPC_BRIDGE_SUPPORT, ScGetBridgeSupport, InRpcBridgeSupport, OutRpcBridgeSupport)\r
+DECLARE_SC("RebootServer", RPC_TEST, ScRebootServer, InRpcTest, OutRpcTest)\r
+DECLARE_SC_EX("GetCaps", CAPSLIST, ScGetCaps, InRpcCapsList, OutRpcCapsList, FreeRpcCapsList)\r
+DECLARE_SC_EX("GetConfig", RPC_CONFIG, ScGetConfig, InRpcConfig, OutRpcConfig, FreeRpcConfig)\r
+DECLARE_SC_EX("SetConfig", RPC_CONFIG, ScSetConfig, InRpcConfig, OutRpcConfig, FreeRpcConfig)\r
+DECLARE_SC_EX("GetHubAdminOptions", RPC_ADMIN_OPTION, ScGetHubAdminOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)\r
+DECLARE_SC_EX("SetHubAdminOptions", RPC_ADMIN_OPTION, ScSetHubAdminOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)\r
+DECLARE_SC_EX("GetHubExtOptions", RPC_ADMIN_OPTION, ScGetHubExtOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)\r
+DECLARE_SC_EX("SetHubExtOptions", RPC_ADMIN_OPTION, ScSetHubExtOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)\r
+DECLARE_SC_EX("GetDefaultHubAdminOptions", RPC_ADMIN_OPTION, ScGetDefaultHubAdminOptions, InRpcAdminOption, OutRpcAdminOption, FreeRpcAdminOption)\r
+DECLARE_SC("AddL3Switch", RPC_L3SW, ScAddL3Switch, InRpcL3Sw, OutRpcL3Sw)\r
+DECLARE_SC("DelL3Switch", RPC_L3SW, ScDelL3Switch, InRpcL3Sw, OutRpcL3Sw)\r
+DECLARE_SC_EX("EnumL3Switch", RPC_ENUM_L3SW, ScEnumL3Switch, InRpcEnumL3Sw, OutRpcEnumL3Sw, FreeRpcEnumL3Sw)\r
+DECLARE_SC("StartL3Switch", RPC_L3SW, ScStartL3Switch, InRpcL3Sw, OutRpcL3Sw)\r
+DECLARE_SC("StopL3Switch", RPC_L3SW, ScStopL3Switch, InRpcL3Sw, OutRpcL3Sw)\r
+DECLARE_SC("AddL3If", RPC_L3IF, ScAddL3If, InRpcL3If, OutRpcL3If)\r
+DECLARE_SC("DelL3If", RPC_L3IF, ScDelL3If, InRpcL3If, OutRpcL3If)\r
+DECLARE_SC_EX("EnumL3If", RPC_ENUM_L3IF, ScEnumL3If, InRpcEnumL3If, OutRpcEnumL3If, FreeRpcEnumL3If)\r
+DECLARE_SC("AddL3Table", RPC_L3TABLE, ScAddL3Table, InRpcL3Table, OutRpcL3Table)\r
+DECLARE_SC("DelL3Table", RPC_L3TABLE, ScDelL3Table, InRpcL3Table, OutRpcL3Table)\r
+DECLARE_SC_EX("EnumL3Table", RPC_ENUM_L3TABLE, ScEnumL3Table, InRpcEnumL3Table, OutRpcEnumL3Table, FreeRpcEnumL3Table)\r
+DECLARE_SC_EX("EnumCrl", RPC_ENUM_CRL, ScEnumCrl, InRpcEnumCrl, OutRpcEnumCrl, FreeRpcEnumCrl)\r
+DECLARE_SC_EX("AddCrl", RPC_CRL, ScAddCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)\r
+DECLARE_SC_EX("DelCrl", RPC_CRL, ScDelCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)\r
+DECLARE_SC_EX("GetCrl", RPC_CRL, ScGetCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)\r
+DECLARE_SC_EX("SetCrl", RPC_CRL, ScSetCrl, InRpcCrl, OutRpcCrl, FreeRpcCrl)\r
+DECLARE_SC_EX("SetAcList", RPC_AC_LIST, ScSetAcList, InRpcAcList, OutRpcAcList, FreeRpcAcList)\r
+DECLARE_SC_EX("GetAcList", RPC_AC_LIST, ScGetAcList, InRpcAcList, OutRpcAcList, FreeRpcAcList)\r
+DECLARE_SC_EX("EnumLogFile", RPC_ENUM_LOG_FILE, ScEnumLogFile, InRpcEnumLogFile, OutRpcEnumLogFile, FreeRpcEnumLogFile)\r
+DECLARE_SC_EX("ReadLogFile", RPC_READ_LOG_FILE, ScReadLogFile, InRpcReadLogFile, OutRpcReadLogFile, FreeRpcReadLogFile)\r
+DECLARE_SC("AddLicenseKey", RPC_TEST, ScAddLicenseKey, InRpcTest, OutRpcTest)\r
+DECLARE_SC("DelLicenseKey", RPC_TEST, ScDelLicenseKey, InRpcTest, OutRpcTest)\r
+DECLARE_SC_EX("EnumLicenseKey", RPC_ENUM_LICENSE_KEY, ScEnumLicenseKey, InRpcEnumLicenseKey, OutRpcEnumLicenseKey, FreeRpcEnumLicenseKey)\r
+DECLARE_SC("GetLicenseStatus", RPC_LICENSE_STATUS, ScGetLicenseStatus, InRpcLicenseStatus, OutRpcLicenseStatus)\r
+DECLARE_SC("SetSysLog", SYSLOG_SETTING, ScSetSysLog, InRpcSysLogSetting, OutRpcSysLogSetting)\r
+DECLARE_SC("GetSysLog", SYSLOG_SETTING, ScGetSysLog, InRpcSysLogSetting, OutRpcSysLogSetting)\r
+DECLARE_SC_EX("EnumEthVLan", RPC_ENUM_ETH_VLAN, ScEnumEthVLan, InRpcEnumEthVLan, OutRpcEnumEthVLan, FreeRpcEnumEthVLan)\r
+DECLARE_SC("SetEnableEthVLan", RPC_TEST, ScSetEnableEthVLan, InRpcTest, OutRpcTest)\r
+DECLARE_SC_EX("SetHubMsg", RPC_MSG, ScSetHubMsg, InRpcMsg, OutRpcMsg, FreeRpcMsg)\r
+DECLARE_SC_EX("GetHubMsg", RPC_MSG, ScGetHubMsg, InRpcMsg, OutRpcMsg, FreeRpcMsg)\r
+DECLARE_SC("Crash", RPC_TEST, ScCrash, InRpcTest, OutRpcTest)\r
+DECLARE_SC_EX("GetAdminMsg", RPC_MSG, ScGetAdminMsg, InRpcMsg, OutRpcMsg, FreeRpcMsg)\r
+DECLARE_SC("Flush", RPC_TEST, ScFlush, InRpcTest, OutRpcTest)\r
+DECLARE_SC("Debug", RPC_TEST, ScDebug, InRpcTest, OutRpcTest)\r
+// RPC 呼び出し関数定義: ここまで\r
+\r
+\r
+// メッセージを設定\r
+UINT StSetHubMsg(ADMIN *a, RPC_MSG *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+\r
+       CHECK_RIGHT;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+       if (UniStrLen(t->Msg) > HUB_MAXMSG_LEN)\r
+       {\r
+               return ERR_MEMORY_NOT_ENOUGH;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+\r
+       h = GetHub(c, hubname);\r
+\r
+       if (h == NULL)\r
+       {\r
+               ret = ERR_HUB_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_msg") != 0)\r
+               {\r
+                       ret = ERR_NOT_ENOUGH_RIGHT;\r
+               }\r
+               else\r
+               {\r
+                       SetHubMsg(h, t->Msg);\r
+               }\r
+\r
+               ReleaseHub(h);\r
+       }\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ret;\r
+}\r
+\r
+// メッセージを取得\r
+UINT StGetHubMsg(ADMIN *a, RPC_MSG *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+\r
+       CHECK_RIGHT;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+       if (UniStrLen(t->Msg) > HUB_MAXMSG_LEN)\r
+       {\r
+               return ERR_MEMORY_NOT_ENOUGH;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+\r
+       FreeRpcMsg(t);\r
+       Zero(t, sizeof(t));\r
+\r
+       h = GetHub(c, hubname);\r
+\r
+       if (h == NULL)\r
+       {\r
+               ret = ERR_HUB_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               t->Msg = GetHubMsg(h);\r
+\r
+               ReleaseHub(h);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// デバッグ機能を実行する\r
+UINT StDebug(ADMIN *a, RPC_TEST *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_TEST t2;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       Zero(&t2, sizeof(t2));\r
+\r
+       ret = SiDebug(s, &t2, t->IntValue, t->StrValue);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               Copy(t, &t2, sizeof(RPC_TEST));\r
+       }\r
+       else\r
+       {\r
+               Zero(t, sizeof(RPC_TEST));\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// 設定ファイルをフラッシュする\r
+UINT StFlush(ADMIN *a, RPC_TEST *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       UINT size;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       size = SiWriteConfigurationFile(s);\r
+\r
+       t->IntValue = size;\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// クラッシュさせる (システム管理者だけが実行できる緊急時用コード)\r
+UINT StCrash(ADMIN *a, RPC_TEST *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+#ifdef OS_WIN32\r
+       MsSetEnableMinidump(false);\r
+#endif // OS_WIN32\r
+\r
+       CrashNow();\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// 管理者向けメッセージを取得する\r
+UINT StGetAdminMsg(ADMIN *a, RPC_MSG *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_WINVER server_ver;\r
+       RPC_WINVER client_ver;\r
+       wchar_t winver_msg_client[3800];\r
+       wchar_t winver_msg_server[3800];\r
+       wchar_t *utvpn_msg;\r
+       UINT tmpsize;\r
+       wchar_t *tmp;\r
+\r
+       FreeRpcMsg(t);\r
+       Zero(t, sizeof(RPC_MSG));\r
+\r
+       // Windows バージョンチェック\r
+       GetWinVer(&server_ver);\r
+       Copy(&client_ver, &a->ClientWinVer, sizeof(RPC_WINVER));\r
+\r
+       Zero(winver_msg_client, sizeof(winver_msg_client));\r
+       Zero(winver_msg_server, sizeof(winver_msg_server));\r
+\r
+       utvpn_msg = _UU("UTVPN_MSG");\r
+\r
+       if (IsSupportedWinVer(&client_ver) == false)\r
+       {\r
+               SYSTEMTIME st;\r
+\r
+               LocalTime(&st);\r
+\r
+               UniFormat(winver_msg_client, sizeof(winver_msg_client), _UU("WINVER_ERROR_FORMAT"),\r
+                       _UU("WINVER_ERROR_PC_LOCAL"),\r
+                       client_ver.Title,\r
+                       _UU("WINVER_ERROR_VPNSERVER"),\r
+                       SUPPORTED_WINDOWS_LIST,\r
+                       _UU("WINVER_ERROR_PC_LOCAL"),\r
+                       _UU("WINVER_ERROR_VPNSERVER"),\r
+                       _UU("WINVER_ERROR_VPNSERVER"),\r
+                       _UU("WINVER_ERROR_VPNSERVER"),\r
+                       st.wYear, st.wMonth);\r
+       }\r
+\r
+       if (IsSupportedWinVer(&server_ver) == false)\r
+       {\r
+               SYSTEMTIME st;\r
+\r
+               LocalTime(&st);\r
+\r
+               UniFormat(winver_msg_server, sizeof(winver_msg_server), _UU("WINVER_ERROR_FORMAT"),\r
+                       _UU("WINVER_ERROR_PC_REMOTE"),\r
+                       server_ver.Title,\r
+                       _UU("WINVER_ERROR_VPNSERVER"),\r
+                       SUPPORTED_WINDOWS_LIST,\r
+                       _UU("WINVER_ERROR_PC_REMOTE"),\r
+                       _UU("WINVER_ERROR_VPNSERVER"),\r
+                       _UU("WINVER_ERROR_VPNSERVER"),\r
+                       _UU("WINVER_ERROR_VPNSERVER"),\r
+                       st.wYear, st.wMonth);\r
+       }\r
+\r
+       tmpsize = UniStrSize(winver_msg_client) + UniStrSize(winver_msg_server) + UniStrSize(utvpn_msg) + 100;\r
+\r
+       tmp = ZeroMalloc(tmpsize);\r
+       UniStrCat(tmp, tmpsize, utvpn_msg);\r
+       UniStrCat(tmp, tmpsize, winver_msg_client);\r
+       UniStrCat(tmp, tmpsize, winver_msg_server);\r
+\r
+       t->Msg = tmp;\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// VLAN 透過設定一覧の取得\r
+UINT StEnumEthVLan(ADMIN *a, RPC_ENUM_ETH_VLAN *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+#ifdef OS_WIN32\r
+       if (GetServerCapsBool(s, "b_support_eth_vlan") == false)\r
+       {\r
+               ret = ERR_NOT_SUPPORTED;\r
+       }\r
+       else\r
+       {\r
+               FreeRpcEnumEthVLan(t);\r
+               Zero(t, sizeof(RPC_ENUM_ETH_VLAN));\r
+\r
+               if (EnumEthVLanWin32(t) == false)\r
+               {\r
+                       ret = ERR_INTERNAL_ERROR;\r
+               }\r
+       }\r
+#else  // OS_WIN32\r
+       ret = ERR_NOT_SUPPORTED;\r
+#endif // OS_WIN32\r
+\r
+       return ret;\r
+}\r
+\r
+// VLAN 透過設定の設定\r
+UINT StSetEnableEthVLan(ADMIN *a, RPC_TEST *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+#ifdef OS_WIN32\r
+       if (GetServerCapsBool(s, "b_support_eth_vlan") == false)\r
+       {\r
+               ret = ERR_NOT_SUPPORTED;\r
+       }\r
+       else if (MsIsAdmin() == false)\r
+       {\r
+               ret = ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+       else\r
+       {\r
+               if (SetVLanEnableStatus(t->StrValue, MAKEBOOL(t->IntValue)) == false)\r
+               {\r
+                       ret = ERR_INTERNAL_ERROR;\r
+               }\r
+       }\r
+#else  // OS_WIN32\r
+       ret = ERR_NOT_SUPPORTED;\r
+#endif // OS_WIN32\r
+\r
+       return ret;\r
+}\r
+\r
+// ライセンス状態の取得\r
+// (ソフトイーサ社の製品 PacketiX VPN の管理に使えるように互換性を残している)\r
+UINT StGetLicenseStatus(ADMIN *a, RPC_LICENSE_STATUS *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       LICENSE_SYSTEM *ls = s->LicenseSystem;\r
+       LICENSE_STATUS status;\r
+\r
+       if (ls == NULL)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       Zero(t, sizeof(RPC_LICENSE_STATUS));\r
+\r
+       // 現在のライセンスステータスを取得\r
+       LiParseCurrentLicenseStatus(ls, &status);\r
+\r
+       t->EditionId = status.Edition;\r
+       StrCpy(t->EditionStr, sizeof(t->EditionStr), status.EditionStr);\r
+       t->SystemId = status.SystemId;\r
+       t->SystemExpires = status.Expires;\r
+       t->NumClientConnectLicense = status.NumClientLicense;\r
+       t->NumBridgeConnectLicense = status.NumBridgeLicense;\r
+       t->NumUserCreationLicense = status.NumUserLicense;\r
+       t->SubscriptionExpires = status.SubscriptionExpires;\r
+       t->IsSubscriptionExpired = status.IsSubscriptionExpired;\r
+       t->NeedSubscription = status.NeedSubscription;\r
+       t->AllowEnterpriseFunction = status.AllowEnterpriseFunction;\r
+       t->ReleaseDate = c->BuiltDate;\r
+\r
+       return ret;\r
+}\r
+\r
+// ライセンスキーの列挙\r
+// (ソフトイーサ社の製品 PacketiX VPN の管理に使えるように互換性を残している)\r
+UINT StEnumLicenseKey(ADMIN *a, RPC_ENUM_LICENSE_KEY *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       LICENSE_SYSTEM *ls = s->LicenseSystem;\r
+\r
+       if (ls == NULL)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       FreeRpcEnumLicenseKey(t);\r
+       Zero(t, sizeof(RPC_ENUM_LICENSE_KEY));\r
+\r
+       LockList(ls->LicenseList);\r
+       {\r
+               UINT i;\r
+\r
+               t->NumItem = LIST_NUM(ls->LicenseList);\r
+               t->Items = ZeroMalloc(sizeof(RPC_ENUM_LICENSE_KEY_ITEM) * t->NumItem);\r
+\r
+               for (i = 0;i < t->NumItem;i++)\r
+               {\r
+                       RPC_ENUM_LICENSE_KEY_ITEM *k = &t->Items[i];\r
+                       LICENSE *e = LIST_DATA(ls->LicenseList, i);\r
+\r
+                       k->Id = e->Id;\r
+                       k->Expires = e->Expires;\r
+                       StrCpy(k->LicenseId, sizeof(k->LicenseId), e->LicenseIdStr);\r
+                       StrCpy(k->LicenseKey, sizeof(k->LicenseKey), e->LicenseKeyStr);\r
+                       StrCpy(k->LicenseName, sizeof(k->LicenseName), e->Name);\r
+                       k->Status = e->Status;\r
+                       k->ProductId = e->ProductId;\r
+                       k->SystemId = e->SystemId;\r
+                       k->SerialId = e->SerialId;\r
+               }\r
+       }\r
+       UnlockList(ls->LicenseList);\r
+\r
+       return ret;\r
+}\r
+\r
+// ライセンスキーの追加\r
+// (ソフトイーサ社の製品 PacketiX VPN の管理に使えるように互換性を残している)\r
+UINT StAddLicenseKey(ADMIN *a, RPC_TEST *t)\r
+{\r
+       return ERR_NOT_SUPPORTED;\r
+}\r
+\r
+// ライセンスキーの削除\r
+// (ソフトイーサ社の製品 PacketiX VPN の管理に使えるように互換性を残している)\r
+UINT StDelLicenseKey(ADMIN *a, RPC_TEST *t)\r
+{\r
+       return ERR_NOT_SUPPORTED;\r
+}\r
+\r
+// ログファイルのダウンロード\r
+BUF *DownloadFileFromServer(RPC *r, char *server_name, char *filepath, UINT total_size, DOWNLOAD_PROC *proc, void *param)\r
+{\r
+       UINT offset;\r
+       BUF *buf;\r
+       // 引数チェック\r
+       if (r == NULL || filepath == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       if (server_name == NULL)\r
+       {\r
+               server_name = "";\r
+       }\r
+\r
+       offset = 0;\r
+\r
+       buf = NewBuf();\r
+\r
+       while (true)\r
+       {\r
+               DOWNLOAD_PROGRESS g;\r
+               RPC_READ_LOG_FILE t;\r
+               UINT ret;\r
+\r
+               Zero(&t, sizeof(t));\r
+               StrCpy(t.FilePath, sizeof(t.FilePath), filepath);\r
+               t.Offset = offset;\r
+               StrCpy(t.ServerName, sizeof(t.ServerName), server_name);\r
+\r
+               ret = ScReadLogFile(r, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // 失敗\r
+                       FreeRpcReadLogFile(&t);\r
+                       FreeBuf(buf);\r
+                       return NULL;\r
+               }\r
+\r
+               if (t.Buffer == NULL)\r
+               {\r
+                       // 最後まで読み込んだ\r
+                       break;\r
+               }\r
+\r
+               // 現在の状況を更新\r
+               offset += t.Buffer->Size;\r
+               Zero(&g, sizeof(g));\r
+               g.Param = param;\r
+               g.CurrentSize = offset;\r
+               g.TotalSize = MAX(total_size, offset);\r
+               g.ProgressPercent = (UINT)(MAKESURE((UINT64)g.CurrentSize * 100ULL / (UINT64)(MAX(g.TotalSize, 1)), 0, 100ULL));\r
+\r
+               WriteBuf(buf, t.Buffer->Buf, t.Buffer->Size);\r
+\r
+               FreeRpcReadLogFile(&t);\r
+\r
+               if (proc != NULL)\r
+               {\r
+                       if (proc(&g) == false)\r
+                       {\r
+                               // ユーザーキャンセル\r
+                               FreeBuf(buf);\r
+                               return NULL;\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (buf->Size == 0)\r
+       {\r
+               // ダウンロード失敗\r
+               FreeBuf(buf);\r
+               return NULL;\r
+       }\r
+\r
+       return buf;\r
+}\r
+\r
+// ログファイルの読み込み\r
+UINT StReadLogFile(ADMIN *a, RPC_READ_LOG_FILE *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       char logfilename[MAX_PATH];\r
+       char servername[MAX_HOST_NAME_LEN + 1];\r
+       UINT offset;\r
+       bool local = true;\r
+\r
+       if (IsEmptyStr(t->FilePath))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       StrCpy(logfilename, sizeof(logfilename), t->FilePath);\r
+       StrCpy(servername, sizeof(servername), t->ServerName);\r
+       offset = t->Offset;\r
+\r
+       if (s->ServerType != SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               GetMachineName(servername, sizeof(servername));\r
+       }\r
+\r
+       // ログファイルを読み込む権限があるかどうか検査する\r
+       if (a->LogFileList == NULL)\r
+       {\r
+               // キャッシュ無し\r
+               return ERR_OBJECT_NOT_FOUND;\r
+       }\r
+       if (CheckLogFileNameFromEnumList(a->LogFileList, logfilename, servername) == false)\r
+       {\r
+               // そのようなファイルは列挙リストに無い\r
+               return ERR_OBJECT_NOT_FOUND;\r
+       }\r
+\r
+       FreeRpcReadLogFile(t);\r
+       Zero(t, sizeof(RPC_READ_LOG_FILE));\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               UINT i;\r
+\r
+               // 要求されたファイルのサーバー名がクラスタメンバのホスト名\r
+               // と一致した場合はリモートサーバー上にファイルが存在するのでそれを読み込む\r
+               LockList(s->FarmMemberList);\r
+               {\r
+                       for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)\r
+                       {\r
+                               FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);\r
+\r
+                               if (f->Me == false)\r
+                               {\r
+                                       if (StrCmpi(f->hostname, servername) == 0)\r
+                                       {\r
+                                               RPC_READ_LOG_FILE tt;\r
+\r
+                                               Zero(&tt, sizeof(tt));\r
+                                               local = false;\r
+\r
+                                               StrCpy(tt.ServerName, sizeof(tt.ServerName), servername);\r
+                                               StrCpy(tt.FilePath, sizeof(tt.FilePath), logfilename);\r
+                                               tt.Offset = offset;\r
+\r
+                                               if (SiCallReadLogFile(s, f, &tt))\r
+                                               {\r
+                                                       if (tt.Buffer != NULL && tt.Buffer->Size > 0)\r
+                                                       {\r
+                                                               t->Buffer = NewBuf();\r
+                                                               WriteBuf(t->Buffer, tt.Buffer->Buf, tt.Buffer->Size);\r
+                                                       }\r
+                                               }\r
+\r
+                                               FreeRpcReadLogFile(&tt);\r
+\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               UnlockList(s->FarmMemberList);\r
+       }\r
+\r
+       // ローカルファイルの読み込み\r
+       if (local)\r
+       {\r
+               SiReadLocalLogFile(s, logfilename, offset, t);\r
+       }\r
+\r
+       if (offset == 0)\r
+       {\r
+               ALog(a, NULL, "LA_READ_LOG_FILE", servername, logfilename);\r
+       }\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// ログファイルの列挙\r
+UINT StEnumLogFile(ADMIN *a, RPC_ENUM_LOG_FILE *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT i;\r
+       bool no_access = false;\r
+\r
+       HUB *h;\r
+\r
+       if (a->ServerAdmin == false)\r
+       {\r
+               h = GetHub(c, a->HubName);\r
+\r
+               if (a->ServerAdmin == false && GetHubAdminOption(h, "no_read_log_file") != 0)\r
+               {\r
+                       no_access = true;\r
+               }\r
+\r
+               ReleaseHub(h);\r
+       }\r
+       else\r
+       {\r
+               if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+               {\r
+                       // クラスタコントローラで管理者がログファイルの一覧を取得する\r
+                       // と高負荷になるため制限している\r
+                       return ERR_NOT_SUPPORTED;\r
+               }\r
+       }\r
+\r
+       if (no_access)\r
+       {\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       FreeRpcEnumLogFile(t);\r
+       Zero(t, sizeof(RPC_ENUM_LOG_FILE));\r
+\r
+       // ローカルのログファイルを列挙する\r
+       SiEnumLocalLogFileList(s, a->ServerAdmin ? NULL : a->HubName, t);\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               UINT i;\r
+               LIST *tt_list = NewListFast(NULL);\r
+\r
+               LockList(s->FarmMemberList);\r
+               {\r
+                       for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)\r
+                       {\r
+                               FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);\r
+\r
+                               if (f->Me == false)\r
+                               {\r
+                                       // 他のメンバ上のログファイルを列挙する\r
+                                       RPC_ENUM_LOG_FILE *tt;\r
+                                       tt = ZeroMalloc(sizeof(RPC_ENUM_LOG_FILE));\r
+\r
+                                       if (SiCallEnumLogFileList(s, f, tt, a->ServerAdmin ? "" : a->HubName))\r
+                                       {\r
+                                               UINT i;\r
+                                               for (i = 0;i < tt->NumItem;i++)\r
+                                               {\r
+                                                       RPC_ENUM_LOG_FILE_ITEM *e = &tt->Items[i];\r
+\r
+                                                       StrCpy(e->ServerName, sizeof(e->ServerName), f->hostname);\r
+                                               }\r
+\r
+                                               Add(tt_list, tt);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               Free(tt);\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               UnlockList(s->FarmMemberList);\r
+\r
+               for (i = 0;i < LIST_NUM(tt_list);i++)\r
+               {\r
+                       RPC_ENUM_LOG_FILE *tt = LIST_DATA(tt_list, i);\r
+\r
+                       AdjoinRpcEnumLogFile(t, tt);\r
+                       FreeRpcEnumLogFile(tt);\r
+\r
+                       Free(tt);\r
+               }\r
+\r
+               ReleaseList(tt_list);\r
+       }\r
+\r
+       // RPC セッションに最後に列挙したログファイル一覧をキャッシュする\r
+       if (a->LogFileList != NULL)\r
+       {\r
+               FreeEnumLogFile(a->LogFileList);\r
+       }\r
+\r
+       a->LogFileList = NewListFast(CmpLogFile);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_ENUM_LOG_FILE_ITEM *e = &t->Items[i];\r
+               LOG_FILE *f = ZeroMalloc(sizeof(LOG_FILE));\r
+\r
+               f->FileSize = e->FileSize;\r
+               f->UpdatedTime = e->UpdatedTime;\r
+               StrCpy(f->Path, sizeof(f->Path), e->FilePath);\r
+               StrCpy(f->ServerName, sizeof(f->ServerName), e->ServerName);\r
+\r
+               Insert(a->LogFileList, f);\r
+       }\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+\r
+// AC リストの取得\r
+UINT StGetAcList(ADMIN *a, RPC_AC_LIST *t)\r
+{\r
+       return ERR_NOT_SUPPORTED;\r
+}\r
+\r
+// AC リストの設定\r
+UINT StSetAcList(ADMIN *a, RPC_AC_LIST *t)\r
+{\r
+       return ERR_NOT_SUPPORTED;\r
+}\r
+\r
+// CRL の設定\r
+UINT StSetCrl(ADMIN *a, RPC_CRL *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       UINT key;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+\r
+       CHECK_RIGHT;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+       key = t->Key;\r
+\r
+       h = GetHub(c, hubname);\r
+\r
+       if (h == NULL)\r
+       {\r
+               ret = ERR_HUB_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_crl_list") != 0)\r
+               {\r
+                       ret = ERR_NOT_ENOUGH_RIGHT;\r
+               }\r
+               else\r
+               {\r
+                       if (h->HubDb == NULL)\r
+                       {\r
+                               ret = ERR_NOT_SUPPORTED;\r
+                       }\r
+                       else\r
+                       {\r
+                               LockList(h->HubDb->CrlList);\r
+                               {\r
+                                       CRL *crl = ListKeyToPointer(h->HubDb->CrlList, t->Key);\r
+\r
+                                       if (crl == NULL)\r
+                                       {\r
+                                               ret = ERR_INTERNAL_ERROR;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               CRL *new_crl = CopyCrl(t->Crl);\r
+                                               if (ReplaceListPointer(h->HubDb->CrlList, crl, new_crl))\r
+                                               {\r
+                                                       ALog(a, h, "LA_ADD_CRL");\r
+                                                       FreeCrl(crl);\r
+\r
+                                                       IncrementServerConfigRevision(s);\r
+                                               }\r
+                                       }\r
+                               }\r
+                               UnlockList(h->HubDb->CrlList);\r
+                       }\r
+               }\r
+\r
+               ReleaseHub(h);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// CRL の取得\r
+UINT StGetCrl(ADMIN *a, RPC_CRL *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       UINT key;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+\r
+       CHECK_RIGHT;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+       key = t->Key;\r
+\r
+       FreeRpcCrl(t);\r
+       Zero(t, sizeof(RPC_CRL));\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+       t->Key = key;\r
+\r
+       h = GetHub(c, hubname);\r
+\r
+       if (h == NULL)\r
+       {\r
+               ret = ERR_HUB_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               if (h->HubDb == NULL)\r
+               {\r
+                       ret = ERR_NOT_SUPPORTED;\r
+               }\r
+               else\r
+               {\r
+                       LockList(h->HubDb->CrlList);\r
+                       {\r
+                               CRL *crl = ListKeyToPointer(h->HubDb->CrlList, t->Key);\r
+\r
+                               if (crl == NULL)\r
+                               {\r
+                                       ret = ERR_INTERNAL_ERROR;\r
+                               }\r
+                               else\r
+                               {\r
+                                       t->Crl = CopyCrl(crl);\r
+                               }\r
+                       }\r
+                       UnlockList(h->HubDb->CrlList);\r
+               }\r
+\r
+               ReleaseHub(h);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// CRL の削除\r
+UINT StDelCrl(ADMIN *a, RPC_CRL *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+\r
+       CHECK_RIGHT;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+\r
+       h = GetHub(c, hubname);\r
+\r
+       if (h == NULL)\r
+       {\r
+               ret = ERR_HUB_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_crl_list") != 0)\r
+               {\r
+                       ret = ERR_NOT_ENOUGH_RIGHT;\r
+               }\r
+               else\r
+               {\r
+                       if (h->HubDb == NULL)\r
+                       {\r
+                               ret = ERR_NOT_SUPPORTED;\r
+                       }\r
+                       else\r
+                       {\r
+                               LockList(h->HubDb->CrlList);\r
+                               {\r
+                                       CRL *crl = ListKeyToPointer(h->HubDb->CrlList, t->Key);\r
+\r
+                                       if (crl == NULL)\r
+                                       {\r
+                                               ret = ERR_INTERNAL_ERROR;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               ALog(a, h, "LA_DEL_CRL");\r
+                                               FreeCrl(crl);\r
+                                               Delete(h->HubDb->CrlList, crl);\r
+                                       }\r
+                               }\r
+                               UnlockList(h->HubDb->CrlList);\r
+                       }\r
+               }\r
+\r
+               ReleaseHub(h);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// CRL の追加\r
+UINT StAddCrl(ADMIN *a, RPC_CRL *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+\r
+       if (c->Bridge)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+\r
+       h = GetHub(c, hubname);\r
+\r
+       if (h == NULL)\r
+       {\r
+               ret = ERR_HUB_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_crl_list") != 0)\r
+               {\r
+                       ret = ERR_NOT_ENOUGH_RIGHT;\r
+               }\r
+               else\r
+               {\r
+                       if (h->HubDb == NULL)\r
+                       {\r
+                               ret = ERR_NOT_SUPPORTED;\r
+                       }\r
+                       else\r
+                       {\r
+                               LockList(h->HubDb->CrlList);\r
+                               {\r
+                                       if (LIST_NUM(h->HubDb->CrlList) < MAX_HUB_CRLS)\r
+                                       {\r
+                                               CRL *crl = CopyCrl(t->Crl);\r
+\r
+                                               Insert(h->HubDb->CrlList, crl);\r
+\r
+                                               ALog(a, h, "LA_SET_CRL");\r
+\r
+                                               IncrementServerConfigRevision(s);\r
+                                       }\r
+                               }\r
+                               UnlockList(h->HubDb->CrlList);\r
+                       }\r
+               }\r
+\r
+               ReleaseHub(h);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// CRL の列挙\r
+UINT StEnumCrl(ADMIN *a, RPC_ENUM_CRL *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+\r
+       CHECK_RIGHT;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+       FreeRpcEnumCrl(t);\r
+       Zero(t, sizeof(RPC_ENUM_CRL));\r
+\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+\r
+       h = GetHub(c, hubname);\r
+\r
+       if (h == NULL)\r
+       {\r
+               ret = ERR_HUB_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               if (h->HubDb == NULL)\r
+               {\r
+                       ret = ERR_NOT_SUPPORTED;\r
+               }\r
+               else\r
+               {\r
+                       LockList(h->HubDb->CrlList);\r
+                       {\r
+                               UINT i;\r
+\r
+                               t->NumItem = LIST_NUM(h->HubDb->CrlList);\r
+                               t->Items = ZeroMalloc(sizeof(RPC_ENUM_CRL_ITEM) * t->NumItem);\r
+\r
+                               for (i = 0;i < LIST_NUM(h->HubDb->CrlList);i++)\r
+                               {\r
+                                       CRL *crl = LIST_DATA(h->HubDb->CrlList, i);\r
+                                       wchar_t *info = GenerateCrlStr(crl);\r
+\r
+                                       UniStrCpy(t->Items[i].CrlInfo, sizeof(t->Items[i].CrlInfo), info);\r
+                                       Free(info);\r
+\r
+                                       t->Items[i].Key = POINTER_TO_KEY(crl);\r
+                               }\r
+                       }\r
+                       UnlockList(h->HubDb->CrlList);\r
+               }\r
+\r
+               ReleaseHub(h);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// ルーティングテーブルの列挙\r
+UINT StEnumL3Table(ADMIN *a, RPC_ENUM_L3TABLE *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       L3SW *sw;\r
+       char name[MAX_HUBNAME_LEN + 1];\r
+\r
+       if (IsEmptyStr(t->Name))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       StrCpy(name, sizeof(name), t->Name);\r
+       FreeRpcEnumL3Table(t);\r
+       Zero(t, sizeof(RPC_ENUM_L3TABLE));\r
+       StrCpy(t->Name, sizeof(t->Name), name);\r
+\r
+       sw = L3GetSw(c, t->Name);\r
+\r
+       if (sw == NULL)\r
+       {\r
+               ret = ERR_LAYER3_SW_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               UINT i;\r
+\r
+               Lock(sw->lock);\r
+               {\r
+                       t->NumItem = LIST_NUM(sw->TableList);\r
+                       t->Items = ZeroMalloc(sizeof(RPC_L3TABLE) * t->NumItem);\r
+\r
+                       for (i = 0;i < t->NumItem;i++)\r
+                       {\r
+                               L3TABLE *tbl = LIST_DATA(sw->TableList, i);\r
+                               RPC_L3TABLE *e = &t->Items[i];\r
+\r
+                               StrCpy(e->Name, sizeof(e->Name), name);\r
+                               e->NetworkAddress = tbl->NetworkAddress;\r
+                               e->SubnetMask = tbl->SubnetMask;\r
+                               e->GatewayAddress = tbl->GatewayAddress;\r
+                               e->Metric = tbl->Metric;\r
+                       }\r
+               }\r
+               Unlock(sw->lock);\r
+\r
+               ReleaseL3Sw(sw);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// ルーティングテーブルの削除\r
+UINT StDelL3Table(ADMIN *a, RPC_L3TABLE *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       L3SW *sw;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       sw = L3GetSw(c, t->Name);\r
+\r
+       if (sw == NULL)\r
+       {\r
+               ret = ERR_LAYER3_SW_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               L3TABLE tbl;\r
+\r
+               Zero(&tbl, sizeof(tbl));\r
+               tbl.NetworkAddress = t->NetworkAddress;\r
+               tbl.SubnetMask = t->SubnetMask;\r
+               tbl.GatewayAddress = t->GatewayAddress;\r
+               tbl.Metric = t->Metric;\r
+\r
+               if (L3DelTable(sw, &tbl) == false)\r
+               {\r
+                       ret = ERR_LAYER3_TABLE_DEL_FAILED;\r
+               }\r
+               else\r
+               {\r
+                       char tmp[MAX_SIZE];\r
+                       IPToStr32(tmp, sizeof(tmp), tbl.NetworkAddress);\r
+                       ALog(a, NULL, "LA_DEL_L3_TABLE", tmp, t->Name);\r
+\r
+                       IncrementServerConfigRevision(s);\r
+               }\r
+\r
+               ReleaseL3Sw(sw);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// ルーティングテーブルの追加\r
+UINT StAddL3Table(ADMIN *a, RPC_L3TABLE *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       L3SW *sw;\r
+\r
+       if (IsNetworkAddress32(t->NetworkAddress, t->SubnetMask) == false ||\r
+               IsHostIPAddress32(t->GatewayAddress) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       sw = L3GetSw(c, t->Name);\r
+\r
+       if (sw == NULL)\r
+       {\r
+               ret = ERR_LAYER3_SW_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               L3TABLE tbl;\r
+\r
+               Zero(&tbl, sizeof(tbl));\r
+               tbl.NetworkAddress = t->NetworkAddress;\r
+               tbl.SubnetMask = t->SubnetMask;\r
+               tbl.GatewayAddress = t->GatewayAddress;\r
+               tbl.Metric = t->Metric;\r
+\r
+               if (L3AddTable(sw, &tbl) == false)\r
+               {\r
+                       ret = ERR_LAYER3_TABLE_ADD_FAILED;\r
+               }\r
+               else\r
+               {\r
+                       char tmp[MAX_SIZE];\r
+                       IPToStr32(tmp, sizeof(tmp), tbl.NetworkAddress);\r
+                       ALog(a, NULL, "LA_ADD_L3_TABLE", tmp, t->Name);\r
+\r
+                       IncrementServerConfigRevision(s);\r
+               }\r
+\r
+               ReleaseL3Sw(sw);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// インターフェイスの列挙\r
+UINT StEnumL3If(ADMIN *a, RPC_ENUM_L3IF *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       L3SW *sw;\r
+       char name[MAX_HUBNAME_LEN + 1];\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       StrCpy(name, sizeof(name), t->Name);\r
+\r
+       FreeRpcEnumL3If(t);\r
+       Zero(t, sizeof(RPC_ENUM_L3IF));\r
+\r
+       StrCpy(t->Name, sizeof(t->Name), name);\r
+\r
+       sw = L3GetSw(c, t->Name);\r
+\r
+       if (sw == NULL)\r
+       {\r
+               ret = ERR_LAYER3_SW_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               Lock(sw->lock);\r
+               {\r
+                       UINT i;\r
+\r
+                       t->NumItem = LIST_NUM(sw->IfList);\r
+                       t->Items = ZeroMalloc(sizeof(RPC_L3IF) * t->NumItem);\r
+\r
+                       for (i = 0;i < t->NumItem;i++)\r
+                       {\r
+                               L3IF *f = LIST_DATA(sw->IfList, i);\r
+                               RPC_L3IF *e = &t->Items[i];\r
+\r
+                               StrCpy(e->Name, sizeof(e->Name), sw->Name);\r
+                               StrCpy(e->HubName, sizeof(e->HubName), f->HubName);\r
+                               e->IpAddress = f->IpAddress;\r
+                               e->SubnetMask = f->SubnetMask;\r
+                       }\r
+               }\r
+               Unlock(sw->lock);\r
+\r
+               ReleaseL3Sw(sw);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// インターフェイスの削除\r
+UINT StDelL3If(ADMIN *a, RPC_L3IF *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       L3SW *sw;\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       sw = L3GetSw(c, t->Name);\r
+\r
+       if (sw == NULL)\r
+       {\r
+               ret = ERR_LAYER3_SW_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               if (L3DelIf(sw, t->HubName) == false)\r
+               {\r
+                       ret = ERR_LAYER3_IF_DEL_FAILED;\r
+               }\r
+               else\r
+               {\r
+                       ALog(a, NULL, "LA_DEL_L3_IF", t->HubName, t->Name);\r
+\r
+                       IncrementServerConfigRevision(s);\r
+               }\r
+               ReleaseL3Sw(sw);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// インターフェイスの追加\r
+UINT StAddL3If(ADMIN *a, RPC_L3IF *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       L3SW *sw;\r
+\r
+       if (IsSubnetMask32(t->SubnetMask) == false || IsHostIPAddress32(t->IpAddress) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+       if ((t->IpAddress & (~t->SubnetMask)) == 0)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       sw = L3GetSw(c, t->Name);\r
+\r
+       if (sw == NULL)\r
+       {\r
+               ret = ERR_LAYER3_SW_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               Lock(sw->lock);\r
+               {\r
+                       if (L3SearchIf(sw, t->HubName) != NULL)\r
+                       {\r
+                               // すでに存在する\r
+                               ret = ERR_LAYER3_IF_EXISTS;\r
+                       }\r
+                       else\r
+                       {\r
+                               if (L3AddIf(sw, t->HubName, t->IpAddress, t->SubnetMask) == false)\r
+                               {\r
+                                       ret = ERR_LAYER3_IF_ADD_FAILED;\r
+                               }\r
+                               else\r
+                               {\r
+                                       ALog(a, NULL, "LA_ADD_L3_IF", t->HubName, t->Name);\r
+\r
+                                       IncrementServerConfigRevision(s);\r
+                               }\r
+                       }\r
+               }\r
+               Unlock(sw->lock);\r
+               ReleaseL3Sw(sw);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// Layer-3 スイッチの停止\r
+UINT StStopL3Switch(ADMIN *a, RPC_L3SW *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       L3SW *sw;\r
+\r
+       if (IsEmptyStr(t->Name))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       sw = L3GetSw(c, t->Name);\r
+\r
+       if (sw == NULL)\r
+       {\r
+               ret = ERR_LAYER3_SW_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               L3SwStop(sw);\r
+               ALog(a, NULL, "LA_STOP_L3_SW", sw->Name);\r
+               ReleaseL3Sw(sw);\r
+\r
+               IncrementServerConfigRevision(s);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// Layer-3 スイッチの開始\r
+UINT StStartL3Switch(ADMIN *a, RPC_L3SW *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       L3SW *sw;\r
+\r
+       if (IsEmptyStr(t->Name))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       sw = L3GetSw(c, t->Name);\r
+\r
+       if (sw == NULL)\r
+       {\r
+               ret = ERR_LAYER3_SW_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               Lock(sw->lock);\r
+               {\r
+                       // 登録されているインターフェイス数を検査する\r
+                       if (LIST_NUM(sw->IfList) >= 1)\r
+                       {\r
+                               L3SwStart(sw);\r
+\r
+                               ALog(a, NULL, "LA_START_L3_SW", sw->Name);\r
+\r
+                               IncrementServerConfigRevision(s);\r
+                       }\r
+                       else\r
+                       {\r
+                               ret = ERR_LAYER3_CANT_START_SWITCH;\r
+                       }\r
+               }\r
+               Unlock(sw->lock);\r
+\r
+               ReleaseL3Sw(sw);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// Layer-3 スイッチの列挙\r
+UINT StEnumL3Switch(ADMIN *a, RPC_ENUM_L3SW *t)\r
+{\r
+       UINT i;\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       FreeRpcEnumL3Sw(t);\r
+       Zero(t, sizeof(RPC_ENUM_L3SW));\r
+\r
+       LockList(c->L3SwList);\r
+       {\r
+               t->NumItem = LIST_NUM(c->L3SwList);\r
+               t->Items = ZeroMalloc(sizeof(RPC_ENUM_L3SW_ITEM) * t->NumItem);\r
+               for (i = 0;i < LIST_NUM(c->L3SwList);i++)\r
+               {\r
+                       L3SW *sw = LIST_DATA(c->L3SwList, i);\r
+                       RPC_ENUM_L3SW_ITEM *e = &t->Items[i];\r
+\r
+                       Lock(sw->lock);\r
+                       {\r
+                               StrCpy(e->Name, sizeof(e->Name), sw->Name);\r
+                               e->NumInterfaces = LIST_NUM(sw->IfList);\r
+                               e->NumTables = LIST_NUM(sw->TableList);\r
+                               e->Active = sw->Active;\r
+                               e->Online = sw->Online;\r
+                       }\r
+                       Unlock(sw->lock);\r
+               }\r
+       }\r
+       UnlockList(c->L3SwList);\r
+\r
+       return ret;\r
+}\r
+\r
+// Layer-3 スイッチの削除\r
+UINT StDelL3Switch(ADMIN *a, RPC_L3SW *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       if (IsEmptyStr(t->Name))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       if (L3DelSw(c, t->Name) == false)\r
+       {\r
+               ret = ERR_LAYER3_SW_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               ALog(a, NULL, "LA_DEL_L3_SW", t->Name);\r
+\r
+               IncrementServerConfigRevision(s);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// Layer-3 スイッチの追加\r
+UINT StAddL3Switch(ADMIN *a, RPC_L3SW *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       L3SW *sw;\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       if (IsEmptyStr(t->Name))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (IsSafeStr(t->Name) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       // 重複チェック\r
+       sw = L3GetSw(c, t->Name);\r
+       if (sw != NULL)\r
+       {\r
+               // すでに存在する\r
+               ReleaseL3Sw(sw);\r
+               ret = ERR_LAYER3_SW_EXISTS;\r
+       }\r
+       else\r
+       {\r
+               LockList(c->L3SwList);\r
+               {\r
+                       if (LIST_NUM(c->L3SwList) >= GetServerCapsInt(s, "i_max_l3_sw"))\r
+                       {\r
+                               // これ以上作成できない\r
+                               sw = NULL;\r
+                       }\r
+                       else\r
+                       {\r
+                               // 作成する\r
+                               sw = L3AddSw(c, t->Name);\r
+\r
+                               if (sw != NULL)\r
+                               {\r
+                                       ALog(a, NULL, "LA_ADD_L3_SW", t->Name);\r
+\r
+                                       IncrementServerConfigRevision(s);\r
+                               }\r
+                       }\r
+               }\r
+               UnlockList(c->L3SwList);\r
+\r
+               if (sw == NULL)\r
+               {\r
+                       // 失敗\r
+                       ret = ERR_INTERNAL_ERROR;\r
+               }\r
+               else\r
+               {\r
+                       // 成功\r
+                       ReleaseL3Sw(sw);\r
+               }\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// 仮想 HUB の拡張オプションを設定する\r
+UINT StSetHubExtOptions(ADMIN *a, RPC_ADMIN_OPTION *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+\r
+       bool not_server_admin = false;\r
+\r
+       if (t->NumItem > MAX_HUB_ADMIN_OPTIONS)\r
+       {\r
+               return ERR_TOO_MANT_ITEMS;\r
+       }\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       if (a->ServerAdmin == false)\r
+       {\r
+               not_server_admin = true;\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (GetHubAdminOption(h, "deny_hub_admin_change_ext_option") && not_server_admin)\r
+       {\r
+               // 十分な管理権限が無い\r
+               ReleaseHub(h);\r
+\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       // 設定の実行\r
+       Lock(h->lock);\r
+       {\r
+               DataToHubOptionStruct(h->Option, t);\r
+       }\r
+       Unlock(h->lock);\r
+\r
+       ALog(a, NULL, "LA_SET_HUB_EXT_OPTION", h->Name);\r
+\r
+       h->CurrentVersion++;\r
+       SiHubUpdateProc(h);\r
+\r
+       ReleaseHub(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// 仮想 HUB の拡張オプションを取得する\r
+UINT StGetHubExtOptions(ADMIN *a, RPC_ADMIN_OPTION *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       FreeRpcAdminOption(t);\r
+       Zero(t, sizeof(RPC_ADMIN_OPTION));\r
+\r
+       StrCpy(t->HubName, sizeof(t->HubName), h->Name);\r
+\r
+       // 設定の取得\r
+       Lock(h->lock);\r
+       {\r
+               HubOptionStructToData(t, h->Option, h->Name);\r
+       }\r
+       Unlock(h->lock);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// 仮想 HUB の管理オプションを設定する\r
+UINT StSetHubAdminOptions(ADMIN *a, RPC_ADMIN_OPTION *t)\r
+{\r
+       UINT i;\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+\r
+       bool not_server_admin = false;\r
+\r
+       if (t->NumItem > MAX_HUB_ADMIN_OPTIONS)\r
+       {\r
+               return ERR_TOO_MANT_ITEMS;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       if (a->ServerAdmin == false)\r
+       {\r
+               not_server_admin = true;\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (GetHubAdminOption(h, "allow_hub_admin_change_option") == false\r
+               && not_server_admin)\r
+       {\r
+               // 十分な管理権限が無い\r
+               ReleaseHub(h);\r
+\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       LockList(h->AdminOptionList);\r
+       {\r
+               DeleteAllHubAdminOption(h, false);\r
+\r
+               for (i = 0;i < t->NumItem;i++)\r
+               {\r
+                       ADMIN_OPTION *e = &t->Items[i];\r
+                       ADMIN_OPTION *a = ZeroMalloc(sizeof(ADMIN_OPTION));\r
+\r
+                       StrCpy(a->Name, sizeof(a->Name), e->Name);\r
+                       a->Value = e->Value;\r
+\r
+                       Insert(h->AdminOptionList, a);\r
+               }\r
+\r
+               AddHubAdminOptionsDefaults(h, false);\r
+       }\r
+       UnlockList(h->AdminOptionList);\r
+\r
+       ALog(a, NULL, "LA_SET_HUB_ADMIN_OPTION", h->Name);\r
+\r
+       h->CurrentVersion++;\r
+       SiHubUpdateProc(h);\r
+\r
+       ReleaseHub(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// 仮想 HUB の管理オプションを取得する\r
+UINT StGetHubAdminOptions(ADMIN *a, RPC_ADMIN_OPTION *t)\r
+{\r
+       UINT i;\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       FreeRpcAdminOption(t);\r
+       Zero(t, sizeof(RPC_ADMIN_OPTION));\r
+\r
+       StrCpy(t->HubName, sizeof(t->HubName), h->Name);\r
+\r
+       LockList(h->AdminOptionList);\r
+       {\r
+               t->NumItem = LIST_NUM(h->AdminOptionList);\r
+               t->Items = ZeroMalloc(sizeof(ADMIN_OPTION) * t->NumItem);\r
+\r
+               for (i = 0;i < t->NumItem;i++)\r
+               {\r
+                       ADMIN_OPTION *a = LIST_DATA(h->AdminOptionList, i);\r
+                       ADMIN_OPTION *e = &t->Items[i];\r
+\r
+                       StrCpy(e->Name, sizeof(e->Name), a->Name);\r
+                       e->Value = a->Value;\r
+               }\r
+       }\r
+       UnlockList(h->AdminOptionList);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// デフォルトの管理オプションの一覧を取得する\r
+UINT StGetDefaultHubAdminOptions(ADMIN *a, RPC_ADMIN_OPTION *t)\r
+{\r
+       UINT i;\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (a->Server->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       FreeRpcAdminOption(t);\r
+       Zero(t, sizeof(RPC_ADMIN_OPTION));\r
+\r
+       t->NumItem = num_admin_options;\r
+       t->Items = ZeroMalloc(sizeof(ADMIN_OPTION) * t->NumItem);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               ADMIN_OPTION *a = &t->Items[i];\r
+\r
+               StrCpy(a->Name, sizeof(a->Name), admin_options[i].Name);\r
+               a->Value = admin_options[i].Value;\r
+       }\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// config の取得\r
+UINT StGetConfig(ADMIN *a, RPC_CONFIG *t)\r
+{\r
+       SERVER *s;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       FreeRpcConfig(t);\r
+       Zero(t, sizeof(RPC_CONFIG));\r
+\r
+       s = a->Server;\r
+\r
+       ALog(a, NULL, "LA_GET_CONFIG");\r
+\r
+       if (s->CfgRw != NULL)\r
+       {\r
+               FOLDER *f = SiWriteConfigurationToCfg(s);\r
+               BUF *b = CfgFolderToBuf(f, true);\r
+\r
+               StrCpy(t->FileName, sizeof(t->FileName), s->CfgRw->FileName + (s->CfgRw->FileName[0] == '@' ? 1 : 0));\r
+\r
+               t->FileData = ZeroMalloc(b->Size + 1);\r
+               Copy(t->FileData, b->Buf, b->Size);\r
+\r
+               CfgDeleteFolder(f);\r
+               FreeBuf(b);\r
+\r
+               return ERR_NO_ERROR;\r
+       }\r
+       else\r
+       {\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+}\r
+\r
+// config の設定\r
+UINT StSetConfig(ADMIN *a, RPC_CONFIG *t)\r
+{\r
+       SERVER *s;\r
+       IO *o;\r
+       char filename[MAX_PATH];\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       s = a->Server;\r
+       if (s->CfgRw == NULL)\r
+       {\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       // 新しい Config ファイルに書き込む\r
+       Format(filename, sizeof(filename), "%s.new", s->CfgRw->FileName);\r
+\r
+       o = FileCreate(filename);\r
+\r
+       FileWrite(o, t->FileData, StrLen(t->FileData));\r
+\r
+       FileClose(o);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       ALog(a, NULL, "LA_SET_CONFIG");\r
+\r
+       // サーバーを再起動する\r
+       SiRebootServer(s->Cedar->Bridge);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// Caps の取得\r
+UINT StGetCaps(ADMIN *a, CAPSLIST *t)\r
+{\r
+       FreeRpcCapsList(t);\r
+       Zero(t, sizeof(CAPSLIST));\r
+\r
+       GetServerCapsMain(a->Server, t);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// サーバーの再起動\r
+UINT StRebootServer(ADMIN *a, RPC_TEST *t)\r
+{\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       ALog(a, NULL, "LA_REBOOT_SERVER");\r
+\r
+       SiRebootServerEx(a->Server->Cedar->Bridge, t->IntValue);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// ローカルブリッジのサポート情報の取得\r
+UINT StGetBridgeSupport(ADMIN *a, RPC_BRIDGE_SUPPORT *t)\r
+{\r
+       Zero(t, sizeof(RPC_BRIDGE_SUPPORT));\r
+\r
+       t->IsBridgeSupportedOs = IsBridgeSupported();\r
+       t->IsWinPcapNeeded = IsNeedWinPcap();\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// Ethernet デバイスの列挙\r
+UINT StEnumEthernet(ADMIN *a, RPC_ENUM_ETH *t)\r
+{\r
+       TOKEN_LIST *o;\r
+       UINT i;\r
+       char tmp[MAX_SIZE];\r
+       bool unix_support = false;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+#ifdef OS_UNIX\r
+       unix_support = EthIsInterfaceDescriptionSupportedUnix();\r
+#endif // OS_UNIX\r
+\r
+       o = GetEthList();\r
+\r
+       FreeRpcEnumEth(t);\r
+       Zero(t, sizeof(RPC_ENUM_ETH));\r
+\r
+       t->NumItem = o->NumTokens;\r
+       t->Items = ZeroMalloc(sizeof(RPC_ENUM_ETH_ITEM) * t->NumItem);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_ENUM_ETH_ITEM *e = &t->Items[i];\r
+\r
+               StrCpy(e->DeviceName, sizeof(e->DeviceName), o->Token[i]);\r
+\r
+               StrCpy(tmp, sizeof(tmp), e->DeviceName);\r
+\r
+#ifdef OS_WIN32\r
+               GetEthNetworkConnectionName(e->NetworkConnectionName, sizeof(e->NetworkConnectionName), e->DeviceName);\r
+#else\r
+               if (unix_support == false)\r
+               {\r
+                       StrCpy(tmp, sizeof(tmp), "");\r
+               }\r
+               else\r
+               {\r
+                       if (EthGetInterfaceDescriptionUnix(e->DeviceName, tmp, sizeof(tmp)) == false)\r
+                       {\r
+                               StrCpy(tmp, sizeof(tmp), e->DeviceName);\r
+                       }\r
+               }\r
+\r
+               StrToUni(e->NetworkConnectionName, sizeof(e->NetworkConnectionName), tmp);\r
+#endif\r
+       }\r
+\r
+       FreeToken(o);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// ローカルブリッジの追加\r
+UINT StAddLocalBridge(ADMIN *a, RPC_LOCALBRIDGE *t)\r
+{\r
+       if (IsEmptyStr(t->DeviceName) || IsEmptyStr(t->HubName))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       if (IsEthSupported() == false)\r
+       {\r
+               return ERR_LOCAL_BRIDGE_UNSUPPORTED;\r
+       }\r
+\r
+       ALog(a, NULL, "LA_ADD_BRIDGE", t->HubName, t->DeviceName);\r
+\r
+       AddLocalBridge(a->Server->Cedar, t->HubName, t->DeviceName, false, false, t->TapMode, NULL, false);\r
+\r
+       IncrementServerConfigRevision(a->Server);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// ローカルブリッジの削除\r
+UINT StDeleteLocalBridge(ADMIN *a, RPC_LOCALBRIDGE *t)\r
+{\r
+       if (IsEmptyStr(t->DeviceName) || IsEmptyStr(t->HubName))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       ALog(a, NULL, "LA_DELETE_BRIDGE", t->HubName, t->DeviceName);\r
+\r
+       if (DeleteLocalBridge(a->Server->Cedar, t->HubName, t->DeviceName) == false)\r
+       {\r
+               return ERR_OBJECT_NOT_FOUND;\r
+       }\r
+\r
+       IncrementServerConfigRevision(a->Server);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// ローカルブリッジの列挙\r
+UINT StEnumLocalBridge(ADMIN *a, RPC_ENUM_LOCALBRIDGE *t)\r
+{\r
+       UINT i;\r
+       CEDAR *c;\r
+\r
+       if (IsEthSupported() == false)\r
+       {\r
+               return ERR_LOCAL_BRIDGE_UNSUPPORTED;\r
+       }\r
+\r
+       FreeRpcEnumLocalBridge(t);\r
+       Zero(t, sizeof(RPC_ENUM_LOCALBRIDGE));\r
+\r
+       c = a->Server->Cedar;\r
+\r
+       LockList(c->LocalBridgeList);\r
+       {\r
+               t->NumItem = LIST_NUM(c->LocalBridgeList);\r
+               t->Items = ZeroMalloc(sizeof(RPC_LOCALBRIDGE) * t->NumItem);\r
+\r
+               for (i = 0;i < t->NumItem;i++)\r
+               {\r
+                       RPC_LOCALBRIDGE *e = &t->Items[i];\r
+                       LOCALBRIDGE *br = LIST_DATA(c->LocalBridgeList, i);\r
+\r
+                       if (br->Bridge == false)\r
+                       {\r
+                               e->Online = e->Active = false;\r
+                       }\r
+                       else\r
+                       {\r
+                               e->Online = true;\r
+                               if (br->Bridge->Active)\r
+                               {\r
+                                       e->Active = true;\r
+                               }\r
+                               else\r
+                               {\r
+                                       e->Active = false;\r
+                               }\r
+                       }\r
+                       StrCpy(e->DeviceName, sizeof(e->DeviceName), br->DeviceName);\r
+                       StrCpy(e->HubName, sizeof(e->HubName), br->HubName);\r
+\r
+                       e->TapMode = br->TapMode;\r
+               }\r
+       }\r
+       UnlockList(c->LocalBridgeList);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// syslog 設定の書き込み\r
+UINT StSetSysLog(ADMIN *a, SYSLOG_SETTING *t)\r
+{\r
+       return ERR_NOT_SUPPORTED;\r
+}\r
+\r
+// syslog 設定の読み込み\r
+UINT StGetSysLog(ADMIN *a, SYSLOG_SETTING *t)\r
+{\r
+       return ERR_NOT_SUPPORTED;\r
+}\r
+\r
+// KEEP の設定\r
+UINT StSetKeep(ADMIN *a, RPC_KEEP *t)\r
+{\r
+       SERVER *s = a->Server;\r
+\r
+       if (t->UseKeepConnect)\r
+       {\r
+               if (IsEmptyStr(t->KeepConnectHost) ||\r
+                       t->KeepConnectPort == 0 ||\r
+                       t->KeepConnectPort >= 65536)\r
+               {\r
+                       return ERR_INVALID_PARAMETER;\r
+               }\r
+       }\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       Lock(s->Keep->lock);\r
+       {\r
+               KEEP *keep = s->Keep;\r
+               keep->Enable = t->UseKeepConnect;\r
+               keep->Server = true;\r
+               StrCpy(keep->ServerName, sizeof(keep->ServerName), t->KeepConnectHost);\r
+               keep->ServerPort = t->KeepConnectPort;\r
+               keep->UdpMode = t->KeepConnectProtocol;\r
+               keep->Interval = t->KeepConnectInterval * 1000;\r
+               if (keep->Interval < 5000)\r
+               {\r
+                       keep->Interval = 5000;\r
+               }\r
+               else if (keep->Interval > 600000)\r
+               {\r
+                       keep->Interval = 600000;\r
+               }\r
+       }\r
+       Unlock(s->Keep->lock);\r
+\r
+       ALog(a, NULL, "LA_SET_KEEP");\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// KEEP の取得\r
+UINT StGetKeep(ADMIN *a, RPC_KEEP *t)\r
+{\r
+       SERVER *s = a->Server;\r
+\r
+       Zero(t, sizeof(RPC_KEEP));\r
+\r
+       Lock(s->Keep->lock);\r
+       {\r
+               KEEP *k = s->Keep;\r
+               t->UseKeepConnect = k->Enable;\r
+               StrCpy(t->KeepConnectHost, sizeof(t->KeepConnectHost), k->ServerName);\r
+               t->KeepConnectPort = k->ServerPort;\r
+               t->KeepConnectProtocol = k->UdpMode;\r
+               t->KeepConnectInterval = k->Interval / 1000;\r
+       }\r
+       Unlock(s->Keep->lock);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// IP テーブルの削除\r
+UINT StDeleteIpTable(ADMIN *a, RPC_DELETE_TABLE *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_delete_iptable") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       LockList(h->IpTable);\r
+       {\r
+               if (IsInListKey(h->IpTable, t->Key))\r
+               {\r
+                       IP_TABLE_ENTRY *e = ListKeyToPointer(h->IpTable, t->Key);\r
+                       Free(e);\r
+                       Delete(h->IpTable, e);\r
+               }\r
+               else\r
+               {\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+               }\r
+       }\r
+       UnlockList(h->IpTable);\r
+\r
+       if (ret == ERR_OBJECT_NOT_FOUND)\r
+       {\r
+               if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+               {\r
+                       UINT i;\r
+                       LockList(s->FarmMemberList);\r
+                       {\r
+                               for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)\r
+                               {\r
+                                       FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);\r
+                                       if (f->Me == false)\r
+                                       {\r
+                                               SiCallDeleteIpTable(s, f, t->HubName, t->Key);\r
+                                               ret = ERR_NO_ERROR;\r
+                                       }\r
+                               }\r
+                       }\r
+                       UnlockList(s->FarmMemberList);\r
+               }\r
+       }\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// ローカル IP テーブルの列挙\r
+UINT SiEnumIpTable(SERVER *s, char *hubname, RPC_ENUM_IP_TABLE *t)\r
+{\r
+       CEDAR *c;\r
+       UINT i;\r
+       HUB *h = NULL;\r
+       // 引数チェック\r
+       if (s == NULL || hubname == NULL || t == NULL)\r
+       {\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       c = s->Cedar;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, hubname);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+\r
+       LockList(h->IpTable);\r
+       {\r
+               t->NumIpTable = LIST_NUM(h->IpTable);\r
+               t->IpTables = ZeroMalloc(sizeof(RPC_ENUM_IP_TABLE_ITEM) * t->NumIpTable);\r
+\r
+               for (i = 0;i < t->NumIpTable;i++)\r
+               {\r
+                       RPC_ENUM_IP_TABLE_ITEM *e = &t->IpTables[i];\r
+                       IP_TABLE_ENTRY *table = LIST_DATA(h->IpTable, i);\r
+\r
+                       e->Key = POINTER_TO_KEY(table);\r
+                       StrCpy(e->SessionName, sizeof(e->SessionName), table->Session->Name);\r
+                       e->Ip = IPToUINT(&table->Ip);\r
+                       Copy(&e->IpV6, &table->Ip, sizeof(IP));\r
+                       e->DhcpAllocated = table->DhcpAllocated;\r
+                       e->CreatedTime = TickToTime(table->CreatedTime);\r
+                       e->UpdatedTime = TickToTime(table->UpdatedTime);\r
+\r
+                       GetMachineName(e->RemoteHostname, sizeof(e->RemoteHostname));\r
+               }\r
+       }\r
+       UnlockList(h->IpTable);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// IP テーブルの列挙\r
+UINT StEnumIpTable(ADMIN *a, RPC_ENUM_IP_TABLE *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       UINT i;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       // ローカルの列挙\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+       FreeRpcEnumIpTable(t);\r
+       Zero(t, sizeof(RPC_ENUM_IP_TABLE));\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+\r
+       ret = SiEnumIpTable(s, hubname, t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               return ret;\r
+       }\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               // リモートの列挙\r
+               LockList(s->FarmMemberList);\r
+               {\r
+                       for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)\r
+                       {\r
+                               FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);\r
+                               if (f->Me == false)\r
+                               {\r
+                                       RPC_ENUM_IP_TABLE tmp;\r
+\r
+                                       Zero(&tmp, sizeof(tmp));\r
+\r
+                                       SiCallEnumIpTable(s, f, hubname, &tmp);\r
+\r
+                                       AdjoinRpcEnumIpTable(t, &tmp);\r
+                                       FreeRpcEnumIpTable(&tmp);\r
+                               }\r
+                       }\r
+               }\r
+               UnlockList(s->FarmMemberList);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// MAC テーブルの削除\r
+UINT StDeleteMacTable(ADMIN *a, RPC_DELETE_TABLE *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_delete_mactable") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       LockList(h->MacTable);\r
+       {\r
+               if (IsInListKey(h->MacTable, t->Key))\r
+               {\r
+                       MAC_TABLE_ENTRY *e = ListKeyToPointer(h->MacTable, t->Key);\r
+                       Free(e);\r
+                       Delete(h->MacTable, e);\r
+               }\r
+               else\r
+               {\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+               }\r
+       }\r
+       UnlockList(h->MacTable);\r
+\r
+       if (ret == ERR_OBJECT_NOT_FOUND)\r
+       {\r
+               if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+               {\r
+                       UINT i;\r
+                       LockList(s->FarmMemberList);\r
+                       {\r
+                               for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)\r
+                               {\r
+                                       FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);\r
+                                       if (f->Me == false)\r
+                                       {\r
+                                               SiCallDeleteMacTable(s, f, t->HubName, t->Key);\r
+                                               ret = ERR_NO_ERROR;\r
+                                       }\r
+                               }\r
+                       }\r
+                       UnlockList(s->FarmMemberList);\r
+               }\r
+       }\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// ローカル MAC テーブルの列挙\r
+UINT SiEnumMacTable(SERVER *s, char *hubname, RPC_ENUM_MAC_TABLE *t)\r
+{\r
+       CEDAR *c;\r
+       UINT i;\r
+       HUB *h = NULL;\r
+       // 引数チェック\r
+       if (s == NULL || hubname == NULL || t == NULL)\r
+       {\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       c = s->Cedar;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, hubname);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+\r
+       LockList(h->MacTable);\r
+       {\r
+               t->NumMacTable = LIST_NUM(h->MacTable);\r
+               t->MacTables = ZeroMalloc(sizeof(RPC_ENUM_MAC_TABLE_ITEM) * t->NumMacTable);\r
+\r
+               for (i = 0;i < t->NumMacTable;i++)\r
+               {\r
+                       RPC_ENUM_MAC_TABLE_ITEM *e = &t->MacTables[i];\r
+                       MAC_TABLE_ENTRY *mac = LIST_DATA(h->MacTable, i);\r
+\r
+                       e->Key = POINTER_TO_KEY(mac);\r
+                       StrCpy(e->SessionName, sizeof(e->SessionName), mac->Session->Name);\r
+                       Copy(e->MacAddress, mac->MacAddress, sizeof(e->MacAddress));\r
+                       e->CreatedTime = TickToTime(mac->CreatedTime);\r
+                       e->UpdatedTime = TickToTime(mac->UpdatedTime);\r
+                       e->VlanId = mac->VlanId;\r
+\r
+                       GetMachineName(e->RemoteHostname, sizeof(e->RemoteHostname));\r
+               }\r
+       }\r
+       UnlockList(h->MacTable);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// MAC テーブルの列挙\r
+UINT StEnumMacTable(ADMIN *a, RPC_ENUM_MAC_TABLE *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       UINT i;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       // ローカルの MAC テーブルを列挙する\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+       FreeRpcEnumMacTable(t);\r
+       Zero(t, sizeof(RPC_ENUM_MAC_TABLE));\r
+\r
+       ret = SiEnumMacTable(s, hubname, t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               return ret;\r
+       }\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               // リモートの MAC テーブルを列挙する\r
+               LockList(s->FarmMemberList);\r
+               {\r
+                       for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)\r
+                       {\r
+                               FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);\r
+                               if (f->Me == false)\r
+                               {\r
+                                       RPC_ENUM_MAC_TABLE tmp;\r
+\r
+                                       Zero(&tmp, sizeof(tmp));\r
+\r
+                                       SiCallEnumMacTable(s, f, hubname, &tmp);\r
+\r
+                                       AdjoinRpcEnumMacTable(t, &tmp);\r
+                                       FreeRpcEnumMacTable(&tmp);\r
+                               }\r
+                       }\r
+               }\r
+               UnlockList(s->FarmMemberList);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// セッションの削除\r
+UINT StDeleteSession(ADMIN *a, RPC_DELETE_SESSION *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       char name[MAX_SESSION_NAME_LEN + 1];\r
+       SESSION *sess;\r
+\r
+       if (IsEmptyStr(t->Name))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+       StrCpy(name, sizeof(name), t->Name);\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_disconnect_session") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       sess = GetSessionByName(h, name);\r
+\r
+       if (sess == NULL)\r
+       {\r
+               if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+               {\r
+                       // ファームコントローラ\r
+                       UINT i;\r
+                       LockList(s->FarmMemberList);\r
+                       {\r
+                               for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)\r
+                               {\r
+                                       FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);\r
+                                       if (f->Me == false)\r
+                                       {\r
+                                               // 切断を試行\r
+                                               SiCallDeleteSession(s, f, t->HubName, t->Name);\r
+                                       }\r
+                               }\r
+                       }\r
+                       UnlockList(s->FarmMemberList);\r
+               }\r
+               else\r
+               {\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if (sess->LinkModeServer)\r
+               {\r
+                       ret = ERR_LINK_CANT_DISCONNECT;\r
+               }\r
+               else if (sess->SecureNATMode)\r
+               {\r
+                       ret = ERR_SNAT_CANT_DISCONNECT;\r
+               }\r
+               else if (sess->BridgeMode)\r
+               {\r
+                       ret = ERR_BRIDGE_CANT_DISCONNECT;\r
+               }\r
+               else if (sess->L3SwitchMode)\r
+               {\r
+                       ret = ERR_LAYER3_CANT_DISCONNECT;\r
+               }\r
+               else\r
+               {\r
+                       StopSession(sess);\r
+               }\r
+               ReleaseSession(sess);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               ALog(a, h, "LA_DELETE_SESSION", t->Name);\r
+       }\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// セッション状態の取得\r
+UINT StGetSessionStatus(ADMIN *a, RPC_SESSION_STATUS *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       char name[MAX_SESSION_NAME_LEN + 1];\r
+       SESSION *sess;\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+       StrCpy(name, sizeof(name), t->Name);\r
+\r
+       if (IsEmptyStr(t->Name))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_query_session") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       FreeRpcSessionStatus(t);\r
+       Zero(t, sizeof(RPC_SESSION_STATUS));\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+       StrCpy(t->Name, sizeof(t->Name), name);\r
+\r
+       sess = GetSessionByName(h, t->Name);\r
+\r
+       if (sess == NULL)\r
+       {\r
+               if (s->ServerType != SERVER_TYPE_FARM_CONTROLLER)\r
+               {\r
+                       // セッションが見つからない\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+               }\r
+               else\r
+               {\r
+                       UINT i;\r
+                       // 自分以外のメンバのセッションも検索してみる\r
+                       LockList(s->FarmMemberList);\r
+                       {\r
+                               for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)\r
+                               {\r
+                                       FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);\r
+                                       if (f->Me == false)\r
+                                       {\r
+                                               RPC_SESSION_STATUS tmp;\r
+                                               Zero(&tmp, sizeof(tmp));\r
+                                               StrCpy(tmp.HubName, sizeof(tmp.HubName), t->HubName);\r
+                                               StrCpy(tmp.Name, sizeof(tmp.Name), t->Name);\r
+\r
+                                               if (SiCallGetSessionStatus(s, f, &tmp))\r
+                                               {\r
+                                                       if (StrLen(tmp.HubName) != 0)\r
+                                                       {\r
+                                                               // セッション情報の取得に成功した\r
+                                                               Copy(t, &tmp, sizeof(RPC_SESSION_STATUS));\r
+                                                               break;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               FreeRpcSessionStatus(&tmp);\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               if (i == LIST_NUM(s->FarmMemberList))\r
+                               {\r
+                                       // 結局見つからない\r
+                                       ret = ERR_OBJECT_NOT_FOUND;\r
+                               }\r
+                       }\r
+                       UnlockList(s->FarmMemberList);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               SESSION *s = sess;\r
+\r
+               Lock(s->lock);\r
+               {\r
+                       StrCpy(t->Username, sizeof(t->Username), s->Username);\r
+                       StrCpy(t->RealUsername, sizeof(t->RealUsername), s->UserNameReal);\r
+                       StrCpy(t->GroupName, sizeof(t->GroupName), s->GroupName);\r
+                       Copy(&t->NodeInfo, &s->NodeInfo, sizeof(NODE_INFO));\r
+\r
+                       if (s->Connection != NULL)\r
+                       {\r
+                               t->ClientIp = IPToUINT(&s->Connection->ClientIp);\r
+                               if (IsIP6(&s->Connection->ClientIp))\r
+                               {\r
+                                       Copy(&t->ClientIp6, &s->Connection->ClientIp.ipv6_addr, sizeof(t->ClientIp6));\r
+                               }\r
+\r
+                               StrCpy(t->ClientHostName, sizeof(t->ClientHostName), s->Connection->ClientHostname);\r
+                       }\r
+               }\r
+               Unlock(s->lock);\r
+\r
+               CiGetSessionStatus(&t->Status, s);\r
+\r
+               ReleaseSession(s);\r
+       }\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// セッションの列挙メイン\r
+void SiEnumSessionMain(SERVER *s, RPC_ENUM_SESSION *t)\r
+{\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       UINT ret = ERR_NO_ERROR;\r
+       UINT num;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (s == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+\r
+       FreeRpcEnumSession(t);\r
+       Zero(t, sizeof(RPC_ENUM_SESSION));\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+\r
+       // ローカルセッションの列挙\r
+       num = 0;\r
+       SiEnumLocalSession(s, hubname, t);\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               // リモートセッションの列挙\r
+               LockList(s->FarmMemberList);\r
+               {\r
+                       for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)\r
+                       {\r
+                               FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);\r
+                               if (f->Me == false)\r
+                               {\r
+                                       RPC_ENUM_SESSION tmp;\r
+\r
+                                       Zero(&tmp, sizeof(tmp));\r
+\r
+                                       SiCallEnumSession(s, f, hubname, &tmp);\r
+\r
+                                       AdjoinRpcEnumSession(t, &tmp);\r
+                                       FreeRpcEnumSession(&tmp);\r
+                               }\r
+                       }\r
+               }\r
+               UnlockList(s->FarmMemberList);\r
+       }\r
+}\r
+\r
+// セッションの列挙\r
+UINT StEnumSession(ADMIN *a, RPC_ENUM_SESSION *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_enum_session") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       SiEnumSessionMain(s, t);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// グループの列挙\r
+UINT StEnumGroup(ADMIN *a, RPC_ENUM_GROUP *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+\r
+       CHECK_RIGHT;\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       AcLock(h);\r
+       {\r
+               UINT i, j;\r
+\r
+               FreeRpcEnumGroup(t);\r
+               Zero(t, sizeof(RPC_ENUM_GROUP));\r
+               StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+\r
+               t->NumGroup = LIST_NUM(h->HubDb->GroupList);\r
+               t->Groups = ZeroMalloc(sizeof(RPC_ENUM_GROUP_ITEM) * t->NumGroup);\r
+\r
+               for (i = 0;i < t->NumGroup;i++)\r
+               {\r
+                       RPC_ENUM_GROUP_ITEM *e = &t->Groups[i];\r
+                       USERGROUP *g = LIST_DATA(h->HubDb->GroupList, i);\r
+\r
+                       Lock(g->lock);\r
+                       {\r
+                               StrCpy(e->Name, sizeof(e->Name), g->Name);\r
+                               UniStrCpy(e->Realname, sizeof(e->Realname), g->RealName);\r
+                               UniStrCpy(e->Note, sizeof(e->Note), g->Note);\r
+                               if (g->Policy != NULL)\r
+                               {\r
+                                       if (g->Policy->Access == false)\r
+                                       {\r
+                                               e->DenyAccess = true;\r
+                                       }\r
+                               }\r
+                       }\r
+                       Unlock(g->lock);\r
+\r
+                       e->NumUsers = 0;\r
+\r
+\r
+                       LockList(h->HubDb->UserList);\r
+                       {\r
+                               for (j = 0;j < LIST_NUM(h->HubDb->UserList);j++)\r
+                               {\r
+                                       USER *u = LIST_DATA(h->HubDb->UserList, j);\r
+\r
+                                       Lock(u->lock);\r
+                                       {\r
+                                               if (u->Group == g)\r
+                                               {\r
+                                                       e->NumUsers++;\r
+                                               }\r
+                                       }\r
+                                       Unlock(u->lock);\r
+                               }\r
+                       }\r
+                       UnlockList(h->HubDb->UserList);\r
+               }\r
+       }\r
+       AcUnlock(h);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// グループの削除\r
+UINT StDeleteGroup(ADMIN *a, RPC_DELETE_USER *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       if (IsEmptyStr(t->Name) || IsSafeStr(t->Name) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_groups") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       AcLock(h);\r
+       {\r
+               if (AcDeleteGroup(h, t->Name) == false)\r
+               {\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+               }\r
+       }\r
+       AcUnlock(h);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               ALog(a, h, "LA_DELETE_GROUP", t->Name);\r
+       }\r
+\r
+       ReleaseHub(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ret;\r
+}\r
+\r
+// グループの取得\r
+UINT StGetGroup(ADMIN *a, RPC_SET_GROUP *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+\r
+       if (IsEmptyStr(t->Name) || IsSafeStr(t->Name) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       AcLock(h);\r
+       {\r
+               USERGROUP *g = AcGetGroup(h, t->Name);\r
+\r
+               if (g == NULL)\r
+               {\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+               }\r
+               else\r
+               {\r
+                       FreeRpcSetGroup(t);\r
+                       Zero(t, sizeof(RPC_SET_GROUP));\r
+\r
+                       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+\r
+                       Lock(g->lock);\r
+                       {\r
+                               StrCpy(t->Name, sizeof(t->Name), g->Name);\r
+                               UniStrCpy(t->Realname, sizeof(t->Realname), g->RealName);\r
+                               UniStrCpy(t->Note, sizeof(t->Note), g->Note);\r
+                               Copy(&t->Traffic, g->Traffic, sizeof(TRAFFIC));\r
+                       }\r
+                       Unlock(g->lock);\r
+\r
+                       t->Policy = GetGroupPolicy(g);\r
+\r
+                       ReleaseGroup(g);\r
+               }\r
+       }\r
+       AcUnlock(h);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// グループの設定\r
+UINT StSetGroup(ADMIN *a, RPC_SET_GROUP *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       if (IsEmptyStr(t->Name) || IsSafeStr(t->Name) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_groups") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       AcLock(h);\r
+       {\r
+               USERGROUP *g = AcGetGroup(h, t->Name);\r
+               if (g == NULL)\r
+               {\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+               }\r
+               else\r
+               {\r
+                       Lock(g->lock);\r
+                       {\r
+                               Free(g->RealName);\r
+                               Free(g->Note);\r
+                               g->RealName = UniCopyStr(t->Realname);\r
+                               g->Note = UniCopyStr(t->Note);\r
+                       }\r
+                       Unlock(g->lock);\r
+\r
+                       SetGroupPolicy(g, t->Policy);\r
+\r
+                       ReleaseGroup(g);\r
+\r
+                       ALog(a, h, "LA_SET_GROUP", t->Name);\r
+               }\r
+       }\r
+       AcUnlock(h);\r
+\r
+       ReleaseHub(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ret;\r
+}\r
+\r
+// グループの作成\r
+UINT StCreateGroup(ADMIN *a, RPC_SET_GROUP *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       if (IsEmptyStr(t->Name) || IsSafeStr(t->Name) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_groups") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       AcLock(h);\r
+       {\r
+               if (AcIsGroup(h, t->Name))\r
+               {\r
+                       ret = ERR_GROUP_ALREADY_EXISTS;\r
+               }\r
+               else\r
+               {\r
+                       USERGROUP *g = NewGroup(t->Name, t->Realname, t->Note);\r
+                       SetGroupPolicy(g, t->Policy);\r
+\r
+                       if ((LIST_NUM(h->HubDb->GroupList) >= GetServerCapsInt(a->Server, "i_max_users_per_hub")) ||\r
+                               ((GetHubAdminOption(h, "max_groups") != 0) && (LIST_NUM(h->HubDb->GroupList) >= GetHubAdminOption(h, "max_groups"))))\r
+                       {\r
+                               ret = ERR_TOO_MANY_GROUP;\r
+                       }\r
+                       else\r
+                       {\r
+                               AcAddGroup(h, g);\r
+                       }\r
+\r
+                       ReleaseGroup(g);\r
+\r
+                       ALog(a, h, "LA_CREATE_GROUP", t->Name);\r
+               }\r
+       }\r
+       AcUnlock(h);\r
+\r
+       ReleaseHub(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ret;\r
+}\r
+\r
+// ユーザーの列挙\r
+UINT StEnumUser(ADMIN *a, RPC_ENUM_USER *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       UINT i, num;\r
+\r
+       CHECK_RIGHT;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       FreeRpcEnumUser(t);\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+\r
+       Zero(t, sizeof(RPC_ENUM_USER));\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+\r
+       LockList(h->HubDb->UserList);\r
+       {\r
+               num = LIST_NUM(h->HubDb->UserList);\r
+\r
+               t->NumUser = num;\r
+               t->Users = ZeroMalloc(sizeof(RPC_ENUM_USER_ITEM) * num);\r
+\r
+               for (i = 0;i < num;i++)\r
+               {\r
+                       USER *u = LIST_DATA(h->HubDb->UserList, i);\r
+\r
+                       Lock(u->lock);\r
+                       {\r
+                               RPC_ENUM_USER_ITEM *e = &t->Users[i];\r
+\r
+                               StrCpy(e->Name, sizeof(e->Name), u->Name);\r
+                               StrCpy(e->GroupName, sizeof(e->GroupName), u->GroupName);\r
+                               UniStrCpy(e->Realname, sizeof(e->Realname), u->RealName);\r
+                               UniStrCpy(e->Note, sizeof(e->Note), u->Note);\r
+                               e->AuthType = u->AuthType;\r
+                               e->LastLoginTime = u->LastLoginTime;\r
+                               e->NumLogin = u->NumLogin;\r
+\r
+                               if (u->Policy != NULL)\r
+                               {\r
+                                       e->DenyAccess = u->Policy->Access ? false : true;\r
+                               }\r
+                       }\r
+                       Unlock(u->lock);\r
+               }\r
+       }\r
+       UnlockList(h->HubDb->UserList);\r
+\r
+       ReleaseHub(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// ユーザーの削除\r
+UINT StDeleteUser(ADMIN *a, RPC_DELETE_USER *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       if (IsEmptyStr(t->Name) || IsUserName(t->Name) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_users") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       ALog(a, h, "LA_DELETE_USER", t->Name);\r
+\r
+       AcLock(h);\r
+       {\r
+               if (AcDeleteUser(h, t->Name) == false)\r
+               {\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+               }\r
+       }\r
+       AcUnlock(h);\r
+\r
+       ReleaseHub(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ret;\r
+}\r
+\r
+// ユーザーの取得\r
+UINT StGetUser(ADMIN *a, RPC_SET_USER *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+       USER *u = NULL;\r
+       USERGROUP *g = NULL;\r
+       char name[MAX_USERNAME_LEN + 1];\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       StrCpy(name, sizeof(name), t->Name);\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+\r
+       if (IsEmptyStr(t->Name) || IsUserName(t->Name) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       FreeRpcSetUser(t);\r
+       Zero(t, sizeof(RPC_SET_USER));\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+       StrCpy(t->Name, sizeof(t->Name), name);\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, hubname);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       AcLock(h);\r
+       {\r
+               u = AcGetUser(h, name);\r
+               if (u == NULL)\r
+               {\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+               }\r
+               else\r
+               {\r
+                       Lock(u->lock);\r
+                       {\r
+                               StrCpy(t->GroupName, sizeof(t->GroupName), u->GroupName);\r
+                               UniStrCpy(t->Realname, sizeof(t->Realname), u->RealName);\r
+                               UniStrCpy(t->Note, sizeof(t->Note), u->Note);\r
+                               t->CreatedTime = u->CreatedTime;\r
+                               t->UpdatedTime = u->UpdatedTime;\r
+                               t->ExpireTime = u->ExpireTime;\r
+\r
+                               t->AuthType = u->AuthType;\r
+                               t->AuthData = CopyAuthData(u->AuthData, t->AuthType);\r
+                               t->NumLogin = u->NumLogin;\r
+                               Copy(&t->Traffic, u->Traffic, sizeof(TRAFFIC));\r
+                               if (u->Policy != NULL)\r
+                               {\r
+                                       t->Policy = ClonePolicy(u->Policy);\r
+                               }\r
+                       }\r
+                       Unlock(u->lock);\r
+\r
+                       ReleaseUser(u);\r
+               }\r
+       }\r
+       AcUnlock(h);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// ユーザーの設定\r
+UINT StSetUser(ADMIN *a, RPC_SET_USER *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+       USER *u = NULL;\r
+       USERGROUP *g = NULL;\r
+\r
+       if (IsEmptyStr(t->Name) || IsUserName(t->Name) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       if (StrCmpi(t->Name, "*") == 0)\r
+       {\r
+               if (t->AuthType != AUTHTYPE_RADIUS && t->AuthType != AUTHTYPE_NT)\r
+               {\r
+                       return ERR_INVALID_PARAMETER;\r
+               }\r
+       }\r
+\r
+       if (t->AuthType == AUTHTYPE_RADIUS ||\r
+               t->AuthType == AUTHTYPE_ROOTCERT ||\r
+               t->AuthType == AUTHTYPE_USERCERT ||\r
+               t->AuthType == AUTHTYPE_NT)\r
+       {\r
+               return ERR_UTVPN_NOT_SUPPORT_THIS_AUTH;\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_users") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       AcLock(h);\r
+       {\r
+               u = AcGetUser(h, t->Name);\r
+               if (u == NULL)\r
+               {\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+               }\r
+               else\r
+               {\r
+                       Lock(u->lock);\r
+                       {\r
+                               if (StrLen(t->GroupName) != 0)\r
+                               {\r
+                                       g = AcGetGroup(h, t->GroupName);\r
+\r
+                                       if (g != NULL)\r
+                                       {\r
+                                               JoinUserToGroup(u, g);\r
+                                               ReleaseGroup(g);\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               ret = ERR_GROUP_NOT_FOUND;\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       JoinUserToGroup(u, NULL);\r
+                               }\r
+\r
+                               if (ret != ERR_GROUP_NOT_FOUND)\r
+                               {\r
+                                       Free(u->RealName);\r
+                                       Free(u->Note);\r
+                                       u->RealName = UniCopyStr(t->Realname);\r
+                                       u->Note = UniCopyStr(t->Note);\r
+                                       SetUserAuthData(u, t->AuthType, CopyAuthData(t->AuthData, t->AuthType));\r
+                                       u->ExpireTime = t->ExpireTime;\r
+                                       u->UpdatedTime = SystemTime64();\r
+\r
+                                       SetUserPolicy(u, t->Policy);\r
+                               }\r
+                       }\r
+                       Unlock(u->lock);\r
+\r
+                       IncrementServerConfigRevision(s);\r
+\r
+                       ReleaseUser(u);\r
+               }\r
+       }\r
+       AcUnlock(h);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               ALog(a, h, "LA_SET_USER", t->Name);\r
+       }\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// ユーザーの作成\r
+UINT StCreateUser(ADMIN *a, RPC_SET_USER *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+       UINT ret = ERR_NO_ERROR;\r
+       USER *u;\r
+       USERGROUP *g = NULL;\r
+\r
+       if (IsEmptyStr(t->Name) || IsUserName(t->Name) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       if (t->AuthType == AUTHTYPE_RADIUS ||\r
+               t->AuthType == AUTHTYPE_ROOTCERT ||\r
+               t->AuthType == AUTHTYPE_USERCERT ||\r
+               t->AuthType == AUTHTYPE_NT)\r
+       {\r
+               return ERR_UTVPN_NOT_SUPPORT_THIS_AUTH;\r
+       }\r
+\r
+       if (IsUserName(t->Name) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (StrCmpi(t->Name, "*") == 0)\r
+       {\r
+               if (t->AuthType != AUTHTYPE_RADIUS && t->AuthType != AUTHTYPE_NT)\r
+               {\r
+                       return ERR_INVALID_PARAMETER;\r
+               }\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_users") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       u = NewUser(t->Name, t->Realname, t->Note, t->AuthType, CopyAuthData(t->AuthData, t->AuthType));\r
+       if (u == NULL)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       u->ExpireTime = t->ExpireTime;\r
+\r
+       SetUserPolicy(u, t->Policy);\r
+\r
+       AcLock(h);\r
+       {\r
+               if ((LIST_NUM(h->HubDb->UserList) >= GetServerCapsInt(a->Server, "i_max_users_per_hub")) ||\r
+                       ((GetHubAdminOption(h, "max_users") != 0) && (LIST_NUM(h->HubDb->UserList) >= GetHubAdminOption(h, "max_users"))))\r
+               {\r
+                       ret = ERR_TOO_MANY_USER;\r
+               }\r
+               else if (SiTooManyUserObjectsInServer(s, false))\r
+               {\r
+                       ret = ERR_TOO_MANY_USERS_CREATED;\r
+                       ALog(a, h, "ERR_128");\r
+               }\r
+               else if (AcIsUser(h, t->Name))\r
+               {\r
+                       ret = ERR_USER_ALREADY_EXISTS;\r
+               }\r
+               else\r
+               {\r
+                       if (StrLen(t->GroupName) != 0)\r
+                       {\r
+                               g = AcGetGroup(h, t->GroupName);\r
+                               if (g == NULL)\r
+                               {\r
+                                       ret = ERR_GROUP_NOT_FOUND;\r
+                               }\r
+                       }\r
+\r
+                       if (ret != ERR_GROUP_NOT_FOUND)\r
+                       {\r
+                               if (g != NULL)\r
+                               {\r
+                                       JoinUserToGroup(u, g);\r
+                                       ReleaseGroup(g);\r
+                               }\r
+\r
+                               AcAddUser(h, u);\r
+                               ALog(a, h, "LA_CREATE_USER", t->Name);\r
+\r
+                               IncrementServerConfigRevision(s);\r
+                       }\r
+               }\r
+       }\r
+       AcUnlock(h);\r
+\r
+       ReleaseUser(u);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// アクセスリストの列挙\r
+UINT StEnumAccess(ADMIN *a, RPC_ENUM_ACCESS_LIST *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT i;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+\r
+       CHECK_RIGHT;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+       FreeRpcEnumAccessList(t);\r
+       Zero(t, sizeof(RPC_ENUM_ACCESS_LIST));\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+\r
+       LockList(h->AccessList);\r
+       {\r
+               t->NumAccess = LIST_NUM(h->AccessList);\r
+               t->Accesses = ZeroMalloc(sizeof(ACCESS) * t->NumAccess);\r
+\r
+               for (i = 0;i < LIST_NUM(h->AccessList);i++)\r
+               {\r
+                       ACCESS *a = &t->Accesses[i];\r
+                       Copy(a, LIST_DATA(h->AccessList, i), sizeof(ACCESS));\r
+               }\r
+       }\r
+       UnlockList(h->AccessList);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// アクセスリストの削除\r
+UINT StDeleteAccess(ADMIN *a, RPC_DELETE_ACCESS *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT i;\r
+       bool exists;\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_access_list") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       exists = false;\r
+\r
+       LockList(h->AccessList);\r
+       {\r
+               for (i = 0;i < LIST_NUM(h->AccessList);i++)\r
+               {\r
+                       ACCESS *access = LIST_DATA(h->AccessList, i);\r
+\r
+                       if (access->Id == t->Id)\r
+                       {\r
+                               Free(access);\r
+                               Delete(h->AccessList, access);\r
+                               exists = true;\r
+\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       UnlockList(h->AccessList);\r
+\r
+       if (exists == false)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_OBJECT_NOT_FOUND;\r
+       }\r
+\r
+       ALog(a, h, "LA_DELETE_ACCESS");\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// アクセスリストの設定\r
+UINT StSetAccessList(ADMIN *a, RPC_ENUM_ACCESS_LIST *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT i;\r
+       bool no_jitter = false;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       if (t->NumAccess > GetServerCapsInt(a->Server, "i_max_access_lists"))\r
+       {\r
+               return ERR_TOO_MANY_ACCESS_LIST;\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       no_jitter = GetHubAdminOption(h, "no_delay_jitter_packet_loss");\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_access_list") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "max_accesslists") != 0 &&\r
+               t->NumAccess > GetHubAdminOption(h, "max_accesslists"))\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_TOO_MANY_ACCESS_LIST;\r
+       }\r
+\r
+       LockList(h->AccessList);\r
+       {\r
+               UINT i;\r
+\r
+               // 古いバージョンのクライアントで対応できない形式のアクセスリストがすでに\r
+               // 存在しないかどうかチェックする\r
+               if (a->ClientBuild < 6560)\r
+               {\r
+                       for (i = 0;i < LIST_NUM(h->AccessList);i++)\r
+                       {\r
+                               ACCESS *access = LIST_DATA(h->AccessList, i);\r
+                               if (access->IsIPv6 ||\r
+                                       access->Jitter != 0 || access->Loss != 0 || access->Delay != 0)\r
+                               {\r
+                                       ret = ERR_VERSION_INVALID;\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if (ret == ERR_NO_ERROR)\r
+               {\r
+                       // すべて削除\r
+                       for (i = 0;i < LIST_NUM(h->AccessList);i++)\r
+                       {\r
+                               ACCESS *access = LIST_DATA(h->AccessList, i);\r
+                               Free(access);\r
+                       }\r
+\r
+                       DeleteAll(h->AccessList);\r
+               }\r
+       }\r
+       UnlockList(h->AccessList);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               ALog(a, h, "LA_SET_ACCESS_LIST", t->NumAccess);\r
+\r
+               // すべてのアクセスリストを追加\r
+               for (i = 0;i < t->NumAccess;i++)\r
+               {\r
+                       ACCESS *a = &t->Accesses[i];\r
+\r
+                       if (no_jitter)\r
+                       {\r
+                               a->Jitter = a->Loss = a->Delay = 0;\r
+                       }\r
+\r
+                       AddAccessList(h, a);\r
+               }\r
+\r
+               IncrementServerConfigRevision(s);\r
+\r
+               h->CurrentVersion++;\r
+               SiHubUpdateProc(h);\r
+       }\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// アクセスリストの追加\r
+UINT StAddAccess(ADMIN *a, RPC_ADD_ACCESS *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       bool no_jitter = false;\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       no_jitter = GetHubAdminOption(h, "no_delay_jitter_packet_loss");\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_access_list") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       if ((LIST_NUM(h->AccessList) >= GetServerCapsInt(a->Server, "i_max_access_lists") ||\r
+               (GetHubAdminOption(h, "max_accesslists") != 0) && (LIST_NUM(h->AccessList) >= GetHubAdminOption(h, "max_accesslists"))))\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_TOO_MANY_ACCESS_LIST;\r
+       }\r
+\r
+       ALog(a, h, "LA_ADD_ACCESS");\r
+\r
+       if (no_jitter)\r
+       {\r
+               t->Access.Jitter = t->Access.Delay = t->Access.Loss = 0;\r
+       }\r
+\r
+       AddAccessList(h, &t->Access);\r
+\r
+       h->CurrentVersion++;\r
+       SiHubUpdateProc(h);\r
+\r
+       ReleaseHub(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// リンクの名前を変更する\r
+UINT StRenameLink(ADMIN *a, RPC_RENAME_LINK *t)\r
+{\r
+       UINT i;\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       LINK *k;\r
+       bool exists = false;\r
+\r
+       if (UniIsEmptyStr(t->OldAccountName) || UniIsEmptyStr(t->NewAccountName))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (s->ServerType != SERVER_TYPE_STANDALONE)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       if (UniStrCmpi(t->NewAccountName, t->OldAccountName) == 0)\r
+       {\r
+               // 古い名前と新しい名前が同一\r
+               return ERR_NO_ERROR;\r
+       }\r
+\r
+       h = GetHub(c, t->HubName);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_cascade") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       k = NULL;\r
+\r
+       // リンクを検索する\r
+       LockList(h->LinkList);\r
+       {\r
+               for (i = 0;i < LIST_NUM(h->LinkList);i++)\r
+               {\r
+                       LINK *kk = LIST_DATA(h->LinkList, i);\r
+                       Lock(kk->lock);\r
+                       {\r
+                               if (UniStrCmpi(kk->Option->AccountName, t->OldAccountName) == 0)\r
+                               {\r
+                                       k = kk;\r
+                                       AddRef(kk->ref);\r
+                               }\r
+                       }\r
+                       Unlock(kk->lock);\r
+\r
+                       if (k != NULL)\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               exists = false;\r
+\r
+               if (k != NULL)\r
+               {\r
+                       // 新しい名前がすでに存在しているリンクの名前と重複するかどうか検査\r
+                       for (i = 0;i < LIST_NUM(h->LinkList);i++)\r
+                       {\r
+                               LINK *kk = LIST_DATA(h->LinkList, i);\r
+                               Lock(kk->lock);\r
+                               {\r
+                                       if (UniStrCmpi(kk->Option->AccountName, t->NewAccountName) == 0)\r
+                                       {\r
+                                               // 重複した\r
+                                               exists = true;\r
+                                       }\r
+                               }\r
+                               Unlock(kk->lock);\r
+                       }\r
+\r
+                       if (exists)\r
+                       {\r
+                               // すでに同一の名前が存在している\r
+                               ret = ERR_LINK_ALREADY_EXISTS;\r
+                       }\r
+                       else\r
+                       {\r
+                               // 変更作業を実施する\r
+                               UniStrCpy(k->Option->AccountName, sizeof(k->Option->AccountName), t->NewAccountName);\r
+\r
+                               ALog(a, h, "LA_RENAME_LINK", t->OldAccountName, t->NewAccountName);\r
+\r
+                               IncrementServerConfigRevision(s);\r
+                       }\r
+               }\r
+       }\r
+       UnlockList(h->LinkList);\r
+\r
+       if (k == NULL)\r
+       {\r
+               // リンクが見つからない\r
+               ReleaseHub(h);\r
+               return ERR_OBJECT_NOT_FOUND;\r
+       }\r
+\r
+       ReleaseLink(k);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// リンクを削除する\r
+UINT StDeleteLink(ADMIN *a, RPC_LINK *t)\r
+{\r
+       UINT i;\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       wchar_t accountname[MAX_ACCOUNT_NAME_LEN + 1];\r
+       LINK *k;\r
+\r
+       if (UniIsEmptyStr(t->AccountName))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (s->ServerType != SERVER_TYPE_STANDALONE)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_cascade") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+       UniStrCpy(accountname, sizeof(accountname), t->AccountName);\r
+       k = NULL;\r
+\r
+       // リンクを検索する\r
+       LockList(h->LinkList);\r
+       {\r
+               for (i = 0;i < LIST_NUM(h->LinkList);i++)\r
+               {\r
+                       LINK *kk = LIST_DATA(h->LinkList, i);\r
+                       Lock(kk->lock);\r
+                       {\r
+                               if (UniStrCmpi(kk->Option->AccountName, accountname) == 0)\r
+                               {\r
+                                       k = kk;\r
+                                       AddRef(kk->ref);\r
+                               }\r
+                       }\r
+                       Unlock(kk->lock);\r
+\r
+                       if (k != NULL)\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       UnlockList(h->LinkList);\r
+\r
+       if (k == NULL)\r
+       {\r
+               // リンクが見つからない\r
+               ReleaseHub(h);\r
+\r
+               return ERR_OBJECT_NOT_FOUND;\r
+       }\r
+\r
+       ALog(a, h, "LA_DELETE_LINK", t->AccountName);\r
+\r
+       SetLinkOffline(k);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       DelLink(h, k);\r
+\r
+       ReleaseLink(k);\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// リンクをオフラインにする\r
+UINT StSetLinkOffline(ADMIN *a, RPC_LINK *t)\r
+{\r
+       UINT i;\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       wchar_t accountname[MAX_ACCOUNT_NAME_LEN + 1];\r
+       LINK *k;\r
+\r
+       if (UniIsEmptyStr(t->AccountName))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (s->ServerType != SERVER_TYPE_STANDALONE)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_cascade") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+       UniStrCpy(accountname, sizeof(accountname), t->AccountName);\r
+       k = NULL;\r
+\r
+       // リンクを検索する\r
+       LockList(h->LinkList);\r
+       {\r
+               for (i = 0;i < LIST_NUM(h->LinkList);i++)\r
+               {\r
+                       LINK *kk = LIST_DATA(h->LinkList, i);\r
+                       Lock(kk->lock);\r
+                       {\r
+                               if (UniStrCmpi(kk->Option->AccountName, accountname) == 0)\r
+                               {\r
+                                       k = kk;\r
+                                       AddRef(kk->ref);\r
+                               }\r
+                       }\r
+                       Unlock(kk->lock);\r
+\r
+                       if (k != NULL)\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       UnlockList(h->LinkList);\r
+\r
+       if (k == NULL)\r
+       {\r
+               // リンクが見つからない\r
+               ReleaseHub(h);\r
+\r
+               return ERR_OBJECT_NOT_FOUND;\r
+       }\r
+\r
+       ALog(a, h, "LA_SET_LINK_OFFLINE", t->AccountName);\r
+\r
+       SetLinkOffline(k);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       ReleaseLink(k);\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// リンクをオンラインにする\r
+UINT StSetLinkOnline(ADMIN *a, RPC_LINK *t)\r
+{\r
+       UINT i;\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       wchar_t accountname[MAX_ACCOUNT_NAME_LEN + 1];\r
+       LINK *k;\r
+\r
+       if (UniIsEmptyStr(t->AccountName))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (s->ServerType != SERVER_TYPE_STANDALONE)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_cascade") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+       UniStrCpy(accountname, sizeof(accountname), t->AccountName);\r
+       k = NULL;\r
+\r
+       // リンクを検索する\r
+       LockList(h->LinkList);\r
+       {\r
+               for (i = 0;i < LIST_NUM(h->LinkList);i++)\r
+               {\r
+                       LINK *kk = LIST_DATA(h->LinkList, i);\r
+                       Lock(kk->lock);\r
+                       {\r
+                               if (UniStrCmpi(kk->Option->AccountName, accountname) == 0)\r
+                               {\r
+                                       k = kk;\r
+                                       AddRef(kk->ref);\r
+                               }\r
+                       }\r
+                       Unlock(kk->lock);\r
+\r
+                       if (k != NULL)\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       UnlockList(h->LinkList);\r
+\r
+       if (k == NULL)\r
+       {\r
+               // リンクが見つからない\r
+               ReleaseHub(h);\r
+\r
+               return ERR_OBJECT_NOT_FOUND;\r
+       }\r
+\r
+       ALog(a, h, "LA_SET_LINK_ONLINE", t->AccountName);\r
+\r
+       SetLinkOnline(k);\r
+\r
+       ReleaseLink(k);\r
+       ReleaseHub(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ret;\r
+}\r
+\r
+// リンク状態の取得\r
+UINT StGetLinkStatus(ADMIN *a, RPC_LINK_STATUS *t)\r
+{\r
+       UINT i;\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       wchar_t accountname[MAX_ACCOUNT_NAME_LEN + 1];\r
+       LINK *k;\r
+       SESSION *sess;\r
+\r
+       if (UniIsEmptyStr(t->AccountName))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (s->ServerType != SERVER_TYPE_STANDALONE)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+       UniStrCpy(accountname, sizeof(accountname), t->AccountName);\r
+       FreeRpcLinkStatus(t);\r
+       Zero(t, sizeof(RPC_LINK_STATUS));\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+       UniStrCpy(t->AccountName, sizeof(t->AccountName), accountname);\r
+\r
+       k = NULL;\r
+\r
+       // リンクを検索する\r
+       LockList(h->LinkList);\r
+       {\r
+               for (i = 0;i < LIST_NUM(h->LinkList);i++)\r
+               {\r
+                       LINK *kk = LIST_DATA(h->LinkList, i);\r
+                       Lock(kk->lock);\r
+                       {\r
+                               if (UniStrCmpi(kk->Option->AccountName, accountname) == 0)\r
+                               {\r
+                                       k = kk;\r
+                                       AddRef(kk->ref);\r
+                               }\r
+                       }\r
+                       Unlock(kk->lock);\r
+\r
+                       if (k != NULL)\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       UnlockList(h->LinkList);\r
+\r
+       if (k == NULL)\r
+       {\r
+               // リンクが見つからない\r
+               ReleaseHub(h);\r
+\r
+               return ERR_OBJECT_NOT_FOUND;\r
+       }\r
+\r
+       // セッションからステータス情報を取得する\r
+       Lock(k->lock);\r
+       {\r
+               sess = k->ClientSession;\r
+               if (sess != NULL)\r
+               {\r
+                       AddRef(sess->ref);\r
+               }\r
+       }\r
+       Unlock(k->lock);\r
+\r
+       if (sess != NULL && k->Offline == false)\r
+       {\r
+               CiGetSessionStatus(&t->Status, sess);\r
+       }\r
+       else\r
+       {\r
+               ret = ERR_LINK_IS_OFFLINE;\r
+       }\r
+       ReleaseSession(sess);\r
+\r
+       ReleaseLink(k);\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// リンクの列挙\r
+UINT StEnumLink(ADMIN *a, RPC_ENUM_LINK *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       UINT i;\r
+\r
+       if (s->ServerType != SERVER_TYPE_STANDALONE)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+       FreeRpcEnumLink(t);\r
+       Zero(t, sizeof(RPC_ENUM_LINK));\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+\r
+       LockList(h->LinkList);\r
+       {\r
+               t->NumLink = LIST_NUM(h->LinkList);\r
+               t->Links = ZeroMalloc(sizeof(RPC_ENUM_LINK_ITEM) * t->NumLink);\r
+\r
+               for (i = 0;i < LIST_NUM(h->LinkList);i++)\r
+               {\r
+                       LINK *k = LIST_DATA(h->LinkList, i);\r
+                       RPC_ENUM_LINK_ITEM *e = &t->Links[i];\r
+\r
+                       Lock(k->lock);\r
+                       {\r
+                               UniStrCpy(e->AccountName, sizeof(e->AccountName), k->Option->AccountName);\r
+                               StrCpy(e->Hostname, sizeof(e->Hostname), k->Option->Hostname);\r
+                               StrCpy(e->HubName, sizeof(e->HubName), k->Option->HubName);\r
+                               e->Online = k->Offline ? false : true;\r
+\r
+                               if (e->Online)\r
+                               {\r
+                                       if (k->ClientSession != NULL)\r
+                                       {\r
+                                               e->ConnectedTime = TickToTime(k->ClientSession->CurrentConnectionEstablishTime);\r
+                                               e->Connected = (k->ClientSession->ClientStatus == CLIENT_STATUS_ESTABLISHED);\r
+                                               e->LastError = k->ClientSession->Err;\r
+                                       }\r
+                               }\r
+                       }\r
+                       Unlock(k->lock);\r
+               }\r
+       }\r
+       UnlockList(h->LinkList);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// リンクの取得\r
+UINT StGetLink(ADMIN *a, RPC_CREATE_LINK *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       UINT i;\r
+       char hubname[MAX_SIZE];\r
+       LINK *k;\r
+\r
+       if (s->ServerType != SERVER_TYPE_STANDALONE)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       if (s->ServerType != SERVER_TYPE_STANDALONE)\r
+       {\r
+               return ERR_LINK_CANT_CREATE_ON_FARM;\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       k = NULL;\r
+\r
+       // リンクを検索する\r
+       LockList(h->LinkList);\r
+       {\r
+               for (i = 0;i < LIST_NUM(h->LinkList);i++)\r
+               {\r
+                       LINK *kk = LIST_DATA(h->LinkList, i);\r
+                       Lock(kk->lock);\r
+                       {\r
+                               if (UniStrCmpi(kk->Option->AccountName, t->ClientOption->AccountName) == 0)\r
+                               {\r
+                                       k = kk;\r
+                                       AddRef(kk->ref);\r
+                               }\r
+                       }\r
+                       Unlock(kk->lock);\r
+\r
+                       if (k != NULL)\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       UnlockList(h->LinkList);\r
+\r
+       if (k == NULL)\r
+       {\r
+               // 見つからなかった\r
+               ReleaseHub(h);\r
+               return ERR_OBJECT_NOT_FOUND;\r
+       }\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+       FreeRpcCreateLink(t);\r
+       Zero(t, sizeof(t));\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+\r
+       Lock(k->lock);\r
+       {\r
+               // 設定の取得\r
+               t->Online = k->Offline ? false : true;\r
+               t->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+               Copy(t->ClientOption, k->Option, sizeof(CLIENT_OPTION));\r
+               t->ClientAuth = CopyClientAuth(k->Auth);\r
+               Copy(&t->Policy, k->Policy, sizeof(POLICY));\r
+\r
+               t->CheckServerCert = k->CheckServerCert;\r
+               t->ServerCert = CloneX(k->ServerCert);\r
+       }\r
+       Unlock(k->lock);\r
+\r
+       ReleaseLink(k);\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// リンクの設定\r
+UINT StSetLink(ADMIN *a, RPC_CREATE_LINK *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       UINT i;\r
+       LINK *k;\r
+\r
+       if (s->ServerType != SERVER_TYPE_STANDALONE)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       if (s->ServerType != SERVER_TYPE_STANDALONE)\r
+       {\r
+               return ERR_LINK_CANT_CREATE_ON_FARM;\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_cascade") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       k = NULL;\r
+\r
+       // リンクを検索する\r
+       LockList(h->LinkList);\r
+       {\r
+               for (i = 0;i < LIST_NUM(h->LinkList);i++)\r
+               {\r
+                       LINK *kk = LIST_DATA(h->LinkList, i);\r
+                       Lock(kk->lock);\r
+                       {\r
+                               if (UniStrCmpi(kk->Option->AccountName, t->ClientOption->AccountName) == 0)\r
+                               {\r
+                                       k = kk;\r
+                                       AddRef(kk->ref);\r
+                               }\r
+                       }\r
+                       Unlock(kk->lock);\r
+\r
+                       if (k != NULL)\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       UnlockList(h->LinkList);\r
+\r
+       if (k == NULL)\r
+       {\r
+               // 見つからなかった\r
+               ReleaseHub(h);\r
+               return ERR_OBJECT_NOT_FOUND;\r
+       }\r
+\r
+       ALog(a, h, "LA_SET_LINK", t->ClientOption->AccountName);\r
+\r
+       Lock(k->lock);\r
+       {\r
+               // 設定の更新\r
+               if (k->ServerCert != NULL)\r
+               {\r
+                       FreeX(k->ServerCert);\r
+                       k->ServerCert = NULL;\r
+               }\r
+\r
+               Copy(k->Option, t->ClientOption, sizeof(CLIENT_OPTION));\r
+               StrCpy(k->Option->DeviceName, sizeof(k->Option->DeviceName), LINK_DEVICE_NAME);\r
+               k->Option->NumRetry = INFINITE;\r
+               k->Option->RetryInterval = 10;\r
+               k->Option->NoRoutingTracking = true;\r
+               CiFreeClientAuth(k->Auth);\r
+               k->Auth = CopyClientAuth(t->ClientAuth);\r
+\r
+               if (t->Policy.Ver3 == false)\r
+               {\r
+                       Copy(k->Policy, &t->Policy, sizeof(UINT) * NUM_POLICY_ITEM_FOR_VER2);\r
+               }\r
+               else\r
+               {\r
+                       Copy(k->Policy, &t->Policy, sizeof(POLICY));\r
+               }\r
+\r
+               k->Option->RequireBridgeRoutingMode = true;     // ブリッジ / ルーティングモード有効\r
+               k->Option->RequireMonitorMode = false;  // モニタモード無効\r
+\r
+               k->CheckServerCert = t->CheckServerCert;\r
+               k->ServerCert = CloneX(t->ServerCert);\r
+       }\r
+       Unlock(k->lock);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       ReleaseLink(k);\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// リンクの作成\r
+UINT StCreateLink(ADMIN *a, RPC_CREATE_LINK *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       UINT i;\r
+       LINK *k;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       if (s->ServerType != SERVER_TYPE_STANDALONE)\r
+       {\r
+               return ERR_LINK_CANT_CREATE_ON_FARM;\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_cascade") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       k = NULL;\r
+\r
+       // 既に同じ名前のリンクが存在しないかどうか調べる\r
+       LockList(h->LinkList);\r
+       {\r
+               for (i = 0;i < LIST_NUM(h->LinkList);i++)\r
+               {\r
+                       LINK *kk = LIST_DATA(h->LinkList, i);\r
+                       Lock(kk->lock);\r
+                       {\r
+                               if (UniStrCmpi(kk->Option->AccountName, t->ClientOption->AccountName) == 0)\r
+                               {\r
+                                       k = kk;\r
+                                       AddRef(kk->ref);\r
+                               }\r
+                       }\r
+                       Unlock(kk->lock);\r
+\r
+                       if (k != NULL)\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       UnlockList(h->LinkList);\r
+\r
+       if (k != NULL)\r
+       {\r
+               // すでに同じ名前のリンクが存在する\r
+               ReleaseLink(k);\r
+               ReleaseHub(h);\r
+               return ERR_LINK_ALREADY_EXISTS;\r
+       }\r
+\r
+       ALog(a, h, "LA_CREATE_LINK", t->ClientOption->AccountName);\r
+\r
+       // リンクの作成\r
+       k = NewLink(c, h, t->ClientOption, t->ClientAuth, &t->Policy);\r
+\r
+       if (k == NULL)\r
+       {\r
+               // 作成失敗\r
+               ret = ERR_INTERNAL_ERROR;\r
+       }\r
+       else\r
+       {\r
+               // サーバー証明書検証設定\r
+               k->CheckServerCert = t->CheckServerCert;\r
+               k->ServerCert = CloneX(t->ServerCert);\r
+\r
+               // オフラインにしておく\r
+               k->Offline = false;\r
+               SetLinkOffline(k);\r
+               ReleaseLink(k);\r
+\r
+               IncrementServerConfigRevision(s);\r
+       }\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// HUB の CA を削除\r
+UINT StDeleteCa(ADMIN *a, RPC_HUB_DELETE_CA *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_cert_list") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       LockList(h->HubDb->RootCertList);\r
+       {\r
+               if (IsInListKey(h->HubDb->RootCertList, t->Key))\r
+               {\r
+                       X *x = ListKeyToPointer(h->HubDb->RootCertList, t->Key);\r
+                       Delete(h->HubDb->RootCertList, x);\r
+                       FreeX(x);\r
+\r
+                       ALog(a, h, "LA_DELETE_CA");\r
+\r
+                       IncrementServerConfigRevision(s);\r
+               }\r
+               else\r
+               {\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+               }\r
+       }\r
+       UnlockList(h->HubDb->RootCertList);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// HUB の CA を取得\r
+UINT StGetCa(ADMIN *a, RPC_HUB_GET_CA *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       UINT key;\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+       key = t->Key;\r
+\r
+       FreeRpcHubGetCa(t);\r
+       Zero(t, sizeof(RPC_HUB_GET_CA));\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       LockList(h->HubDb->RootCertList);\r
+       {\r
+               if (IsInListKey(h->HubDb->RootCertList, key))\r
+               {\r
+                       X *x = ListKeyToPointer(h->HubDb->RootCertList, key);\r
+\r
+                       t->Cert = CloneX(x);\r
+               }\r
+               else\r
+               {\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+               }\r
+       }\r
+       UnlockList(h->HubDb->RootCertList);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// HUB の CA を列挙\r
+UINT StEnumCa(ADMIN *a, RPC_HUB_ENUM_CA *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       UINT i;\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+\r
+       FreeRpcHubEnumCa(t);\r
+       Zero(t, sizeof(RPC_HUB_ENUM_CA));\r
+\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, hubname);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_HUB_ENUM_CA));\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+\r
+       if (h->HubDb->RootCertList != NULL)\r
+       {\r
+               LockList(h->HubDb->RootCertList);\r
+               {\r
+                       t->NumCa = LIST_NUM(h->HubDb->RootCertList);\r
+                       t->Ca = ZeroMalloc(sizeof(RPC_HUB_ENUM_CA_ITEM) * t->NumCa);\r
+\r
+                       for (i = 0;i < t->NumCa;i++)\r
+                       {\r
+                               RPC_HUB_ENUM_CA_ITEM *e = &t->Ca[i];\r
+                               X *x = LIST_DATA(h->HubDb->RootCertList, i);\r
+\r
+                               e->Key = POINTER_TO_KEY(x);\r
+                               GetAllNameFromNameEx(e->SubjectName, sizeof(e->SubjectName), x->subject_name);\r
+                               GetAllNameFromNameEx(e->IssuerName, sizeof(e->IssuerName), x->issuer_name);\r
+                               e->Expires = x->notAfter;\r
+                       }\r
+               }\r
+               UnlockList(h->HubDb->RootCertList);\r
+       }\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// HUB へ CA を追加\r
+UINT StAddCa(ADMIN *a, RPC_HUB_ADD_CA *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       if (c->Bridge)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       if (t->Cert == NULL)\r
+       {\r
+               ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (t->Cert->is_compatible_bit == false)\r
+       {\r
+               return ERR_NOT_RSA_1024;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_cert_list") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       ALog(a, h, "LA_ADD_CA");\r
+\r
+       AddRootCert(h, t->Cert);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// HUB ログ設定の取得\r
+UINT StGetHubLog(ADMIN *a, RPC_HUB_LOG *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       GetHubLogSetting(h, &t->LogSetting);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// HUB ログ設定の設定\r
+UINT StSetHubLog(ADMIN *a, RPC_HUB_LOG *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_log_config") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       ALog(a, h, "LA_SET_HUB_LOG");\r
+\r
+       SetHubLogSettingEx(h, &t->LogSetting,\r
+               (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_log_switch_type") != 0));\r
+\r
+       h->CurrentVersion++;\r
+       SiHubUpdateProc(h);\r
+\r
+       ReleaseHub(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// HUB 状態の取得\r
+UINT StGetHubStatus(ADMIN *a, RPC_HUB_STATUS *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_HUB_STATUS));\r
+\r
+       Lock(h->lock);\r
+       {\r
+               StrCpy(t->HubName, sizeof(t->HubName), h->Name);\r
+               t->HubType = h->Type;\r
+               t->Online = h->Offline ? false : true;\r
+               t->NumSessions = LIST_NUM(h->SessionList);\r
+               t->NumSessionsClient = Count(h->NumSessionsClient);\r
+               t->NumSessionsBridge = Count(h->NumSessionsBridge);\r
+               t->NumAccessLists = LIST_NUM(h->AccessList);\r
+\r
+               if (h->HubDb != NULL)\r
+               {\r
+                       t->NumUsers = LIST_NUM(h->HubDb->UserList);\r
+                       t->NumGroups = LIST_NUM(h->HubDb->GroupList);\r
+               }\r
+\r
+               t->NumMacTables = LIST_NUM(h->MacTable);\r
+               t->NumIpTables = LIST_NUM(h->IpTable);\r
+\r
+               Lock(h->TrafficLock);\r
+               {\r
+                       Copy(&t->Traffic, h->Traffic, sizeof(TRAFFIC));\r
+               }\r
+               Unlock(h->TrafficLock);\r
+\r
+               t->NumLogin = h->NumLogin;\r
+               t->LastCommTime = h->LastCommTime;\r
+               t->LastLoginTime = h->LastLoginTime;\r
+               t->CreatedTime = h->CreatedTime;\r
+       }\r
+       Unlock(h->lock);\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               UINT i;\r
+               LockList(s->FarmMemberList);\r
+               {\r
+                       for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)\r
+                       {\r
+                               UINT k;\r
+                               FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);\r
+\r
+                               if (f->Me == false)\r
+                               {\r
+                                       LockList(f->HubList);\r
+                                       {\r
+                                               for (k = 0;k < LIST_NUM(f->HubList);k++)\r
+                                               {\r
+                                                       HUB_LIST *h = LIST_DATA(f->HubList, k);\r
+\r
+                                                       if (StrCmpi(h->Name, t->HubName) == 0)\r
+                                                       {\r
+                                                               t->NumSessions += h->NumSessions;\r
+                                                               t->NumSessionsClient += h->NumSessionsClient;\r
+                                                               t->NumSessionsBridge += h->NumSessionsBridge;\r
+                                                               t->NumMacTables += h->NumMacTables;\r
+                                                               t->NumIpTables += h->NumIpTables;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                                       UnlockList(f->HubList);\r
+                               }\r
+                       }\r
+               }\r
+               UnlockList(s->FarmMemberList);\r
+       }\r
+\r
+       if (h->Type != HUB_TYPE_FARM_STATIC)\r
+       {\r
+               t->SecureNATEnabled = h->EnableSecureNAT;\r
+       }\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// HUB の SecureNAT を有効にする\r
+UINT StEnableSecureNAT(ADMIN *a, RPC_HUB *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (h->Type == HUB_TYPE_FARM_STATIC || GetServerCapsBool(s, "b_support_securenat") == false)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_securenat") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       ALog(a, h, "LA_ENABLE_SNAT");\r
+\r
+       EnableSecureNAT(h, true);\r
+\r
+       h->CurrentVersion++;\r
+       SiHubUpdateProc(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// HUB の SecureNAT を無効にする\r
+UINT StDisableSecureNAT(ADMIN *a, RPC_HUB *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (h->Type == HUB_TYPE_FARM_STATIC || GetServerCapsBool(s, "b_support_securenat") == false)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_securenat") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       ALog(a, h, "LA_DISABLE_SNAT");\r
+\r
+       EnableSecureNAT(h, false);\r
+\r
+       h->CurrentVersion++;\r
+       SiHubUpdateProc(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// NAT エントリの列挙\r
+UINT StEnumNAT(ADMIN *a, RPC_ENUM_NAT *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       UINT i;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (h->Type == HUB_TYPE_FARM_STATIC || GetServerCapsBool(s, "b_support_securenat") == false)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       Lock(h->lock_online);\r
+       {\r
+               if (h->SecureNAT == NULL)\r
+               {\r
+                       ret = ERR_SNAT_NOT_RUNNING;\r
+               }\r
+               else\r
+               {\r
+                       NtEnumNatList(h->SecureNAT->Nat, t);\r
+               }\r
+       }\r
+       Unlock(h->lock_online);\r
+\r
+       if (h->Type == HUB_TYPE_FARM_DYNAMIC)\r
+       {\r
+               if (ret == ERR_SNAT_NOT_RUNNING)\r
+               {\r
+                       // リモートの SecureNAT の状態取得\r
+                       LockList(s->FarmMemberList);\r
+                       {\r
+                               for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)\r
+                               {\r
+                                       FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);\r
+                                       if (f->Me == false)\r
+                                       {\r
+                                               RPC_ENUM_NAT tmp;\r
+\r
+                                               Zero(&tmp, sizeof(tmp));\r
+\r
+                                               SiCallEnumNat(s, f, hubname, &tmp);\r
+\r
+                                               if (tmp.NumItem >= 1)\r
+                                               {\r
+                                                       FreeRpcEnumNat(t);\r
+                                                       Copy(t, &tmp, sizeof(RPC_ENUM_NAT));\r
+                                                       ret = ERR_NO_ERROR;\r
+                                                       break;\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       FreeRpcEnumNat(&tmp);\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       UnlockList(s->FarmMemberList);\r
+               }\r
+       }\r
+\r
+       ReleaseHub(h);\r
+\r
+       ret = ERR_NO_ERROR;\r
+\r
+       return ret;\r
+}\r
+\r
+// SecureNAT の状態の取得\r
+UINT StGetSecureNATStatus(ADMIN *a, RPC_NAT_STATUS *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       UINT i;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (h->Type == HUB_TYPE_FARM_STATIC || GetServerCapsBool(s, "b_support_securenat") == false)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       Lock(h->lock_online);\r
+       {\r
+               if (h->SecureNAT == NULL)\r
+               {\r
+                       ret = ERR_SNAT_NOT_RUNNING;\r
+               }\r
+               else\r
+               {\r
+                       NtGetStatus(h->SecureNAT->Nat, t);\r
+               }\r
+       }\r
+       Unlock(h->lock_online);\r
+\r
+       if (h->Type == HUB_TYPE_FARM_DYNAMIC)\r
+       {\r
+               if (ret == ERR_SNAT_NOT_RUNNING)\r
+               {\r
+                       // リモートの SecureNAT の状態取得\r
+                       LockList(s->FarmMemberList);\r
+                       {\r
+                               for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)\r
+                               {\r
+                                       FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);\r
+                                       if (f->Me == false)\r
+                                       {\r
+                                               RPC_NAT_STATUS tmp;\r
+\r
+                                               Zero(&tmp, sizeof(tmp));\r
+\r
+                                               SiCallGetNatStatus(s, f, hubname, &tmp);\r
+\r
+                                               if (tmp.NumDhcpClients == 0 && tmp.NumTcpSessions == 0 && tmp.NumUdpSessions == 0)\r
+                                               {\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       Copy(t, &tmp, sizeof(RPC_NAT_STATUS));\r
+                                                       ret = ERR_NO_ERROR;\r
+                                                       break;\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       UnlockList(s->FarmMemberList);\r
+               }\r
+       }\r
+\r
+       ReleaseHub(h);\r
+\r
+       ret = ERR_NO_ERROR;\r
+\r
+       return ret;\r
+}\r
+\r
+// DHCP エントリの列挙\r
+UINT StEnumDHCP(ADMIN *a, RPC_ENUM_DHCP *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       UINT i;\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (h->Type == HUB_TYPE_FARM_STATIC || GetServerCapsBool(s, "b_support_securenat") == false)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       Lock(h->lock_online);\r
+       {\r
+               if (h->SecureNAT == NULL)\r
+               {\r
+                       ret = ERR_SNAT_NOT_RUNNING;\r
+               }\r
+               else\r
+               {\r
+                       NtEnumDhcpList(h->SecureNAT->Nat, t);\r
+               }\r
+       }\r
+       Unlock(h->lock_online);\r
+\r
+       if (h->Type == HUB_TYPE_FARM_DYNAMIC)\r
+       {\r
+               if (ret == ERR_SNAT_NOT_RUNNING)\r
+               {\r
+                       // リモートの DHCP の状態取得\r
+                       LockList(s->FarmMemberList);\r
+                       {\r
+                               for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)\r
+                               {\r
+                                       FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);\r
+                                       if (f->Me == false)\r
+                                       {\r
+                                               RPC_ENUM_DHCP tmp;\r
+\r
+                                               Zero(&tmp, sizeof(tmp));\r
+\r
+                                               SiCallEnumDhcp(s, f, hubname, &tmp);\r
+\r
+                                               if (tmp.NumItem >= 1)\r
+                                               {\r
+                                                       FreeRpcEnumDhcp(t);\r
+                                                       Copy(t, &tmp, sizeof(RPC_ENUM_DHCP));\r
+                                                       ret = ERR_NO_ERROR;\r
+                                                       break;\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       FreeRpcEnumDhcp(&tmp);\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       UnlockList(s->FarmMemberList);\r
+               }\r
+       }\r
+\r
+       ReleaseHub(h);\r
+\r
+       ret = ERR_NO_ERROR;\r
+\r
+       return ret;\r
+}\r
+\r
+// SecureNATOption を設定する\r
+UINT StSetSecureNATOption(ADMIN *a, VH_OPTION *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+\r
+       if (IsZero(t->MacAddress, sizeof(t->MacAddress)) ||\r
+               IsHostIPAddress4(&t->Ip) == false ||\r
+               IsSubnetMask4(&t->Mask) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+       if ((IPToUINT(&t->Ip) & (~(IPToUINT(&t->Mask)))) == 0)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (h->Type == HUB_TYPE_FARM_STATIC || GetServerCapsBool(s, "b_support_securenat") == false)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && GetHubAdminOption(h, "no_securenat") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       if (h->SecureNATOption->UseNat == false && t->UseNat)\r
+       {\r
+               if (a->ServerAdmin == false && GetHubAdminOption(h, "no_securenat_enablenat") != 0)\r
+               {\r
+                       ReleaseHub(h);\r
+                       return ERR_NOT_ENOUGH_RIGHT;\r
+               }\r
+       }\r
+\r
+       if (h->SecureNATOption->UseDhcp == false && t->UseDhcp)\r
+       {\r
+               if (a->ServerAdmin == false && GetHubAdminOption(h, "no_securenat_enabledhcp") != 0)\r
+               {\r
+                       ReleaseHub(h);\r
+                       return ERR_NOT_ENOUGH_RIGHT;\r
+               }\r
+       }\r
+\r
+       Copy(h->SecureNATOption, t, sizeof(VH_OPTION));\r
+\r
+       if (h->Type != HUB_TYPE_STANDALONE && h->Cedar != NULL && h->Cedar->Server != NULL &&\r
+               h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               NiClearUnsupportedVhOptionForDynamicHub(h->SecureNATOption, false);\r
+       }\r
+\r
+       Lock(h->lock_online);\r
+       {\r
+               if (h->SecureNAT != NULL)\r
+               {\r
+                       SetVirtualHostOption(h->SecureNAT->Nat->Virtual, t);\r
+               }\r
+       }\r
+       Unlock(h->lock_online);\r
+\r
+       ALog(a, h, "LA_SET_SNAT_OPTION");\r
+\r
+       h->CurrentVersion++;\r
+       SiHubUpdateProc(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// SecureNATOption を取得する\r
+UINT StGetSecureNATOption(ADMIN *a, VH_OPTION *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+\r
+       StrCpy(hubname, sizeof(hubname), t->HubName);\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (h->Type == HUB_TYPE_FARM_STATIC || GetServerCapsBool(s, "b_support_securenat") == false)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       Zero(t, sizeof(VH_OPTION));\r
+       StrCpy(t->HubName, sizeof(t->HubName), hubname);\r
+       Copy(t, h->SecureNATOption, sizeof(VH_OPTION));\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// HUB をオンラインまたはオフラインにする\r
+UINT StSetHubOnline(ADMIN *a, RPC_SET_HUB_ONLINE *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && t->Online && GetHubAdminOption(h, "no_online") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       if (a->ServerAdmin == false && t->Online == false && GetHubAdminOption(h, "no_offline") != 0)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_ENOUGH_RIGHT;\r
+       }\r
+\r
+       if (t->Online)\r
+       {\r
+               ALog(a, h, "LA_SET_HUB_ONLINE");\r
+               SetHubOnline(h);\r
+       }\r
+       else\r
+       {\r
+               ALog(a, h, "LA_SET_HUB_OFFLINE");\r
+               SetHubOffline(h);\r
+       }\r
+\r
+       h->CurrentVersion++;\r
+       SiHubUpdateProc(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// コネクション情報の取得\r
+UINT StGetConnectionInfo(ADMIN *a, RPC_CONNECTION_INFO *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       CONNECTION *connection;\r
+       char name[MAX_CONNECTION_NAME_LEN + 1];\r
+\r
+       if (IsEmptyStr(t->Name))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       LockList(c->ConnectionList);\r
+       {\r
+               CONNECTION tt;\r
+               Zero(&tt, sizeof(tt));\r
+               tt.Name = t->Name;\r
+               StrCpy(name, sizeof(name), t->Name);\r
+\r
+               connection = Search(c->ConnectionList, &tt);\r
+\r
+               if (connection != NULL)\r
+               {\r
+                       AddRef(connection->ref);\r
+               }\r
+       }\r
+       UnlockList(c->ConnectionList);\r
+\r
+       if (connection == NULL)\r
+       {\r
+               return ERR_OBJECT_NOT_FOUND;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_CONNECTION_INFO));\r
+       StrCpy(t->Name, sizeof(t->Name), name);\r
+\r
+       Lock(connection->lock);\r
+       {\r
+               SOCK *s = connection->FirstSock;\r
+\r
+               if (s != NULL)\r
+               {\r
+                       t->Ip = IPToUINT(&s->RemoteIP);\r
+                       t->Port = s->RemotePort;\r
+                       StrCpy(t->Hostname, sizeof(t->Hostname), s->RemoteHostname);\r
+               }\r
+\r
+               StrCpy(t->Name, sizeof(t->Name), connection->Name);\r
+               t->ConnectedTime = TickToTime(connection->ConnectedTick);\r
+               t->Type = connection->Type;\r
+\r
+               StrCpy(t->ServerStr, sizeof(t->ServerStr), connection->ServerStr);\r
+               StrCpy(t->ClientStr, sizeof(t->ClientStr), connection->ClientStr);\r
+               t->ServerVer = connection->ServerVer;\r
+               t->ServerBuild = connection->ServerBuild;\r
+               t->ClientVer = connection->ClientVer;\r
+               t->ClientBuild = connection->ClientBuild;\r
+       }\r
+       Unlock(connection->lock);\r
+\r
+       ReleaseConnection(connection);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// コネクションの切断\r
+UINT StDisconnectConnection(ADMIN *a, RPC_DISCONNECT_CONNECTION *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       CONNECTION *connection;\r
+\r
+       if (IsEmptyStr(t->Name))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       LockList(c->ConnectionList);\r
+       {\r
+               CONNECTION tt;\r
+               Zero(&tt, sizeof(tt));\r
+               tt.Name = t->Name;\r
+\r
+               connection = Search(c->ConnectionList, &tt);\r
+               if (connection != NULL)\r
+               {\r
+                       AddRef(connection->ref);\r
+               }\r
+       }\r
+       UnlockList(c->ConnectionList);\r
+\r
+       if (connection == NULL)\r
+       {\r
+               return ERR_OBJECT_NOT_FOUND;\r
+       }\r
+\r
+       StopConnection(connection, true);\r
+\r
+       ReleaseConnection(connection);\r
+\r
+       ALog(a, NULL, "LA_DISCONNECT_CONN", t->Name);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// コネクションの列挙\r
+UINT StEnumConnection(ADMIN *a, RPC_ENUM_CONNECTION *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       FreeRpcEnumConnetion(t);\r
+       Zero(t, sizeof(RPC_ENUM_CONNECTION));\r
+\r
+       LockList(c->ConnectionList);\r
+       {\r
+               UINT i;\r
+               t->NumConnection = LIST_NUM(c->ConnectionList);\r
+               t->Connections = ZeroMalloc(sizeof(RPC_ENUM_CONNECTION_ITEM) * t->NumConnection);\r
+               \r
+               for (i = 0;i < t->NumConnection;i++)\r
+               {\r
+                       RPC_ENUM_CONNECTION_ITEM *e = &t->Connections[i];\r
+                       CONNECTION *connection = LIST_DATA(c->ConnectionList, i);\r
+\r
+                       Lock(connection->lock);\r
+                       {\r
+                               SOCK *s = connection->FirstSock;\r
+\r
+                               if (s != NULL)\r
+                               {\r
+                                       e->Ip = IPToUINT(&s->RemoteIP);\r
+                                       e->Port = s->RemotePort;\r
+                                       StrCpy(e->Hostname, sizeof(e->Hostname), s->RemoteHostname);\r
+                               }\r
+\r
+                               StrCpy(e->Name, sizeof(e->Name), connection->Name);\r
+                               e->ConnectedTime = TickToTime(connection->ConnectedTick);\r
+                               e->Type = connection->Type;\r
+                       }\r
+                       Unlock(connection->lock);\r
+               }\r
+       }\r
+       UnlockList(c->ConnectionList);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// HUB の Radius オプションの設定\r
+UINT StSetHubRadius(ADMIN *a, RPC_RADIUS *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       SetRadiusServerEx(h, t->RadiusServerName, t->RadiusPort, t->RadiusSecret, t->RadiusRetryInterval);\r
+\r
+       ALog(a, h, "LA_SET_HUB_RADIUS");\r
+\r
+       ReleaseHub(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// HUB の Radius オプションの取得\r
+UINT StGetHubRadius(ADMIN *a, RPC_RADIUS *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+\r
+       CHECK_RIGHT;\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       Zero(t, sizeof(t));\r
+       GetRadiusServerEx(h, t->RadiusServerName, sizeof(t->RadiusServerName),\r
+               &t->RadiusPort, t->RadiusSecret, sizeof(t->RadiusSecret), &t->RadiusRetryInterval);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// HUB の削除\r
+UINT StDeleteHub(ADMIN *a, RPC_DELETE_HUB *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       if (IsEmptyStr(t->HubName) || IsSafeStr(t->HubName) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       StopHub(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       DelHub(c, h);\r
+       ReleaseHub(h);\r
+\r
+       ALog(a, NULL, "LA_DELETE_HUB", t->HubName);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// HUB の列挙\r
+UINT StEnumHub(ADMIN *a, RPC_ENUM_HUB *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h = NULL;\r
+\r
+       FreeRpcEnumHub(t);\r
+\r
+       Zero(t, sizeof(RPC_ENUM_HUB));\r
+\r
+       LockHubList(c);\r
+       {\r
+               UINT i, num, j;\r
+\r
+               num = 0;\r
+\r
+               for (i = 0;i < LIST_NUM(c->HubList);i++)\r
+               {\r
+                       HUB *h = LIST_DATA(c->HubList, i);\r
+\r
+                       Lock(h->lock);\r
+\r
+                       if (a->ServerAdmin == false &&\r
+                               h->Option != NULL &&\r
+                               StrCmpi(h->Name, a->HubName) != 0)\r
+                       {\r
+                               // 列挙を許可しない\r
+                       }\r
+                       else\r
+                       {\r
+                               // 列挙を許可する\r
+                               num++;\r
+                       }\r
+               }\r
+\r
+               t->NumHub = num;\r
+\r
+               t->Hubs = ZeroMalloc(sizeof(RPC_ENUM_HUB_ITEM) * num);\r
+\r
+               i = 0;\r
+               for (j = 0;j < LIST_NUM(c->HubList);j++)\r
+               {\r
+                       HUB *h = LIST_DATA(c->HubList, j);\r
+\r
+                       if (a->ServerAdmin == false &&\r
+                               h->Option != NULL &&\r
+                               StrCmpi(h->Name, a->HubName) != 0)\r
+                       {\r
+                               // 列挙許可しない\r
+                       }\r
+                       else\r
+                       {\r
+                               // 列挙許可\r
+                               RPC_ENUM_HUB_ITEM *e = &t->Hubs[i++];\r
+\r
+                               StrCpy(e->HubName, sizeof(e->HubName), h->Name);\r
+                               e->Online = h->Offline ? false : true;\r
+                               e->HubType = h->Type;\r
+\r
+                               e->NumSessions = LIST_NUM(h->SessionList);\r
+\r
+                               LockList(h->MacTable);\r
+                               {\r
+                                       e->NumMacTables = LIST_NUM(h->MacTable);\r
+                               }\r
+                               UnlockList(h->MacTable);\r
+\r
+                               LockList(h->IpTable);\r
+                               {\r
+                                       e->NumIpTables = LIST_NUM(h->IpTable);\r
+                               }\r
+                               UnlockList(h->IpTable);\r
+\r
+                               if (h->HubDb != NULL)\r
+                               {\r
+                                       LockList(h->HubDb->UserList);\r
+                                       {\r
+                                               e->NumUsers = LIST_NUM(h->HubDb->UserList);\r
+                                       }\r
+                                       UnlockList(h->HubDb->UserList);\r
+\r
+                                       LockList(h->HubDb->GroupList);\r
+                                       {\r
+                                               e->NumGroups = LIST_NUM(h->HubDb->GroupList);\r
+                                       }\r
+                                       UnlockList(h->HubDb->GroupList);\r
+                               }\r
+\r
+                               e->LastCommTime = h->LastCommTime;\r
+                               e->LastLoginTime = h->LastLoginTime;\r
+                               e->NumLogin = h->NumLogin;\r
+                               e->CreatedTime = h->CreatedTime;\r
+                       }\r
+\r
+                       Unlock(h->lock);\r
+               }\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               UINT i, j, k;\r
+               LockList(s->FarmMemberList);\r
+               {\r
+                       for (i = 0;i < LIST_NUM(s->FarmMemberList);i++)\r
+                       {\r
+                               FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);\r
+\r
+                               LockList(f->HubList);\r
+                               {\r
+                                       if (f->Me == false)\r
+                                       {\r
+                                               for (j = 0;j < LIST_NUM(f->HubList);j++)\r
+                                               {\r
+                                                       HUB_LIST *o = LIST_DATA(f->HubList, j);\r
+\r
+                                                       for (k = 0;k < t->NumHub;k++)\r
+                                                       {\r
+                                                               RPC_ENUM_HUB_ITEM *e = &t->Hubs[k];\r
+\r
+                                                               if (StrCmpi(e->HubName, o->Name) == 0)\r
+                                                               {\r
+                                                                       e->NumIpTables += o->NumIpTables;\r
+                                                                       e->NumMacTables += o->NumMacTables;\r
+                                                                       e->NumSessions += o->NumSessions;\r
+                                                               }\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               }\r
+                               UnlockList(f->HubList);\r
+                       }\r
+               }\r
+               UnlockList(s->FarmMemberList);\r
+       }\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// HUB 設定を取得する\r
+UINT StGetHub(ADMIN *a, RPC_CREATE_HUB *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT ret = ERR_NO_ERROR;\r
+       HUB *h;\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       if (IsEmptyStr(t->HubName) || IsSafeStr(t->HubName) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+       CHECK_RIGHT;\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       Zero(t, sizeof(RPC_CREATE_HUB));\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       Lock(h->lock);\r
+       {\r
+               StrCpy(t->HubName, sizeof(t->HubName), h->Name);\r
+               t->Online = h->Offline ? false : true;\r
+               t->HubOption.MaxSession = h->Option->MaxSession;\r
+               t->HubOption.NoEnum = h->Option->NoEnum;\r
+               t->HubType = h->Type;\r
+       }\r
+       Unlock(h->lock);\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// HUB 設定を更新する\r
+UINT StSetHub(ADMIN *a, RPC_CREATE_HUB *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       if (IsEmptyStr(t->HubName) || IsSafeStr(t->HubName) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       CHECK_RIGHT;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       if (s->ServerType == SERVER_TYPE_STANDALONE)\r
+       {\r
+               if (t->HubType != HUB_TYPE_STANDALONE)\r
+               {\r
+                       return ERR_INVALID_PARAMETER;\r
+               }\r
+       }\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               if (t->HubType == HUB_TYPE_STANDALONE)\r
+               {\r
+                       return ERR_INVALID_PARAMETER;\r
+               }\r
+       }\r
+\r
+       LockHubList(c);\r
+       {\r
+               h = GetHub(c, t->HubName);\r
+       }\r
+       UnlockHubList(c);\r
+\r
+       if (h == NULL)\r
+       {\r
+               return ERR_HUB_NOT_FOUND;\r
+       }\r
+\r
+       if (h->Type != t->HubType)\r
+       {\r
+               ReleaseHub(h);\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       if (IsZero(t->HashedPassword, sizeof(t->HashedPassword)) == false &&\r
+               IsZero(t->SecurePassword, sizeof(t->SecurePassword)) == false)\r
+       {\r
+               if (a->ServerAdmin == false && GetHubAdminOption(h, "no_change_admin_password") != 0)\r
+               {\r
+                       ReleaseHub(h);\r
+                       return ERR_NOT_ENOUGH_RIGHT;\r
+               }\r
+       }\r
+\r
+       // 設定しようとしているパスワードが空白かどうか調べる\r
+       {\r
+               UCHAR hash1[SHA1_SIZE], hash2[SHA1_SIZE];\r
+               HashPassword(hash1, ADMINISTRATOR_USERNAME, "");\r
+               Hash(hash2, "", 0, true);\r
+\r
+               if (Cmp(t->HashedPassword, hash2, SHA1_SIZE) == 0 || Cmp(t->SecurePassword, hash1, SHA1_SIZE) == 0)\r
+               {\r
+                       if (a->ServerAdmin == false && a->Rpc->Sock->RemoteIP.addr[0] != 127)\r
+                       {\r
+                               // ローカル以外から仮想 NUB 管理者モードで接続中に\r
+                               // 仮想 HUB のパスワードを空白に設定しようとすると拒否する\r
+                               ReleaseHub(h);\r
+                               return ERR_INVALID_PARAMETER;\r
+                       }\r
+               }\r
+       }\r
+\r
+       Lock(h->lock);\r
+       {\r
+               if (a->ServerAdmin == false && h->Type != t->HubType)\r
+               {\r
+                       ret = ERR_NOT_ENOUGH_RIGHT;\r
+               }\r
+               else\r
+               {\r
+                       h->Type = t->HubType;\r
+                       h->Option->MaxSession = t->HubOption.MaxSession;\r
+                       h->Option->NoEnum = t->HubOption.NoEnum;\r
+                       if (IsZero(t->HashedPassword, sizeof(t->HashedPassword)) == false &&\r
+                               IsZero(t->SecurePassword, sizeof(t->SecurePassword)) == false)\r
+                       {\r
+                               Copy(h->HashedPassword, t->HashedPassword, SHA1_SIZE);\r
+                               Copy(h->SecurePassword, t->SecurePassword, SHA1_SIZE);\r
+                       }\r
+               }\r
+       }\r
+       Unlock(h->lock);\r
+\r
+       if (t->Online)\r
+       {\r
+               if (a->ServerAdmin || GetHubAdminOption(h, "no_online") == 0)\r
+               {\r
+                       SetHubOnline(h);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if (a->ServerAdmin || GetHubAdminOption(h, "no_offline") == 0)\r
+               {\r
+                       SetHubOffline(h);\r
+               }\r
+       }\r
+\r
+       if (h->Type == HUB_TYPE_FARM_STATIC)\r
+       {\r
+               EnableSecureNAT(h, false);\r
+       }\r
+\r
+       h->CurrentVersion++;\r
+       SiHubUpdateProc(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       ALog(a, h, "LA_SET_HUB");\r
+\r
+       ReleaseHub(h);\r
+\r
+       return ret;\r
+}\r
+\r
+// HUB を作成する\r
+UINT StCreateHub(ADMIN *a, RPC_CREATE_HUB *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       HUB *h;\r
+       HUB_OPTION o;\r
+       UINT current_hub_num;\r
+       bool b;\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       if (IsEmptyStr(t->HubName) || IsSafeStr(t->HubName) == false)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       Trim(t->HubName);\r
+       if (StrLen(t->HubName) == 0)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+       if (StartWith(t->HubName, ".") || EndWith(t->HubName, "."))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (s->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       if (s->ServerType == SERVER_TYPE_STANDALONE)\r
+       {\r
+               if (t->HubType != HUB_TYPE_STANDALONE)\r
+               {\r
+                       return ERR_INVALID_PARAMETER;\r
+               }\r
+       }\r
+       else if (t->HubType != HUB_TYPE_FARM_DYNAMIC && t->HubType != HUB_TYPE_FARM_STATIC)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // HUB の作成\r
+       Zero(&o, sizeof(o));\r
+       o.MaxSession = t->HubOption.MaxSession;\r
+       o.NoEnum = t->HubOption.NoEnum;\r
+       o.ManageOnlyPrivateIP = true;\r
+       o.ManageOnlyLocalUnicastIPv6 = true;\r
+       o.NoMacAddressLog = true;\r
+       o.NoIPv6DefaultRouterInRAWhenIPv6 = true;\r
+\r
+       LockList(c->HubList);\r
+       {\r
+               current_hub_num = LIST_NUM(c->HubList);\r
+       }\r
+       UnlockList(c->HubList);\r
+\r
+       if (current_hub_num > GetServerCapsInt(a->Server, "i_max_hubs"))\r
+       {\r
+               return ERR_TOO_MANY_HUBS;\r
+       }\r
+\r
+       LockList(c->HubList);\r
+       {\r
+               b = IsHub(c, t->HubName);\r
+       }\r
+       UnlockList(c->HubList);\r
+\r
+       if (b)\r
+       {\r
+               return ERR_HUB_ALREADY_EXISTS;\r
+       }\r
+\r
+       ALog(a, NULL, "LA_CREATE_HUB", t->HubName);\r
+\r
+       h = NewHub(c, t->HubName, &o);\r
+       Copy(h->HashedPassword, t->HashedPassword, SHA1_SIZE);\r
+       Copy(h->SecurePassword, t->SecurePassword, SHA1_SIZE);\r
+\r
+       h->Type = t->HubType;\r
+\r
+       AddHub(c, h);\r
+\r
+       if (t->Online)\r
+       {\r
+               h->Offline = true;\r
+               SetHubOnline(h);\r
+       }\r
+       else\r
+       {\r
+               h->Offline = false;\r
+               SetHubOffline(h);\r
+       }\r
+\r
+       h->CreatedTime = SystemTime64();\r
+\r
+       ReleaseHub(h);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// 暗号化アルゴリズムを設定する\r
+UINT StSetServerCipher(ADMIN *a, RPC_STR *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+\r
+       if (IsEmptyStr(t->String))\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       StrUpper(t->String);\r
+\r
+       if (CheckCipherListName(t->String) == false)\r
+       {\r
+               return ERR_CIPHER_NOT_SUPPORTED;\r
+       }\r
+       else\r
+       {\r
+               ALog(a, NULL, "LA_SET_SERVER_CIPHER", t->String);\r
+       }\r
+\r
+       Lock(c->lock);\r
+       {\r
+               SetCedarCipherList(c, t->String);\r
+       }\r
+       Unlock(c->lock);\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// 暗号化アルゴリズムを取得する\r
+UINT StGetServerCipher(ADMIN *a, RPC_STR *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+\r
+       FreeRpcStr(t);\r
+       Zero(t, sizeof(RPC_STR));\r
+\r
+       Lock(c->lock);\r
+       {\r
+               t->String = CopyStr(c->CipherList);\r
+       }\r
+       Unlock(c->lock);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// サーバー証明書を取得する\r
+UINT StGetServerCert(ADMIN *a, RPC_KEY_PAIR *t)\r
+{\r
+       bool admin;\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+\r
+       admin = a->ServerAdmin;\r
+\r
+       FreeRpcKeyPair(t);\r
+       Zero(t, sizeof(RPC_KEY_PAIR));\r
+\r
+       Lock(c->lock);\r
+       {\r
+               t->Cert = CloneX(c->ServerX);\r
+               if (admin)\r
+               {\r
+                       t->Key = CloneK(c->ServerK);\r
+               }\r
+       }\r
+       Unlock(c->lock);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// サーバー証明書を設定する\r
+UINT StSetServerCert(ADMIN *a, RPC_KEY_PAIR *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       if (t->Cert == NULL || t->Key == NULL)\r
+       {\r
+               return ERR_PROTOCOL_ERROR;\r
+       }\r
+\r
+       if (t->Cert->is_compatible_bit == false)\r
+       {\r
+               return ERR_NOT_RSA_1024;\r
+       }\r
+\r
+       if (CheckXandK(t->Cert, t->Key) == false)\r
+       {\r
+               return ERR_PROTOCOL_ERROR;\r
+       }\r
+\r
+       SetCedarCert(c, t->Cert, t->Key);\r
+\r
+       ALog(a, NULL, "LA_SET_SERVER_CERT");\r
+\r
+       IncrementServerConfigRevision(s);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// サーバーファームコントローラへの接続状態を取得する\r
+UINT StGetFarmConnectionStatus(ADMIN *a, RPC_FARM_CONNECTION_STATUS *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       FARM_CONTROLLER *fc;\r
+\r
+       if (s->ServerType != SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return ERR_NOT_FARM_MEMBER;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_FARM_CONNECTION_STATUS));\r
+\r
+       fc = s->FarmController;\r
+\r
+       Lock(fc->lock);\r
+       {\r
+               if (fc->Sock != NULL)\r
+               {\r
+                       t->Ip = IPToUINT(&fc->Sock->RemoteIP);\r
+                       t->Port = fc->Sock->RemotePort;\r
+               }\r
+\r
+               t->Online = fc->Online;\r
+               t->LastError = ERR_NO_ERROR;\r
+\r
+               if (t->Online == false)\r
+               {\r
+                       t->LastError = fc->LastError;\r
+               }\r
+               else\r
+               {\r
+                       t->CurrentConnectedTime = fc->CurrentConnectedTime;\r
+               }\r
+\r
+               t->StartedTime = fc->StartedTime;\r
+               t->FirstConnectedTime = fc->FirstConnectedTime;\r
+\r
+               t->NumConnected = fc->NumConnected;\r
+               t->NumTry = fc->NumTry;\r
+               t->NumFailed = fc->NumFailed;\r
+       }\r
+       Unlock(fc->lock);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// サーバーファームメンバ列挙\r
+UINT StEnumFarmMember(ADMIN *a, RPC_ENUM_FARM *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       CEDAR *c = s->Cedar;\r
+       UINT i;\r
+\r
+       FreeRpcEnumFarm(t);\r
+       Zero(t, sizeof(RPC_ENUM_FARM));\r
+\r
+       if (s->ServerType != SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_FARM));\r
+\r
+       LockList(s->FarmMemberList);\r
+       {\r
+               t->NumFarm = LIST_NUM(s->FarmMemberList);\r
+               t->Farms = ZeroMalloc(sizeof(RPC_ENUM_FARM_ITEM) * t->NumFarm);\r
+\r
+               for (i = 0;i < t->NumFarm;i++)\r
+               {\r
+                       FARM_MEMBER *f = LIST_DATA(s->FarmMemberList, i);\r
+                       RPC_ENUM_FARM_ITEM *e = &t->Farms[i];\r
+\r
+                       e->Id = POINTER_TO_KEY(f);\r
+                       e->Controller = f->Me;\r
+\r
+                       if (e->Controller)\r
+                       {\r
+                               e->ConnectedTime = TickToTime(c->CreatedTick);\r
+                               e->Ip = 0x0100007f;\r
+                               GetMachineName(e->Hostname, sizeof(e->Hostname));\r
+                               e->Point = f->Point;\r
+                               e->NumSessions = Count(c->CurrentSessions);\r
+                               e->NumTcpConnections = Count(c->CurrentTcpConnections);\r
+\r
+                               e->AssignedBridgeLicense = Count(c->AssignedBridgeLicense);\r
+                               e->AssignedClientLicense = Count(c->AssignedClientLicense);\r
+                       }\r
+                       else\r
+                       {\r
+                               e->ConnectedTime = f->ConnectedTime;\r
+                               e->Ip = f->Ip;\r
+                               StrCpy(e->Hostname, sizeof(e->Hostname), f->hostname);\r
+                               e->Point = f->Point;\r
+                               e->NumSessions = f->NumSessions;\r
+                               e->NumTcpConnections = f->NumTcpConnections;\r
+\r
+                               e->AssignedBridgeLicense = f->AssignedBridgeLicense;\r
+                               e->AssignedClientLicense = f->AssignedClientLicense;\r
+                       }\r
+                       e->NumHubs = LIST_NUM(f->HubList);\r
+               }\r
+       }\r
+       UnlockList(s->FarmMemberList);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// サーバーファームメンバ情報の取得\r
+UINT StGetFarmInfo(ADMIN *a, RPC_FARM_INFO *t)\r
+{\r
+       SERVER *s = a->Server;\r
+       UINT id = t->Id;\r
+       UINT i;\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       FreeRpcFarmInfo(t);\r
+       Zero(t, sizeof(RPC_FARM_INFO));\r
+\r
+       if (s->ServerType != SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               return ERR_NOT_FARM_CONTROLLER;\r
+       }\r
+\r
+       LockList(s->FarmMemberList);\r
+       {\r
+               if (IsInListKey(s->FarmMemberList, id))\r
+               {\r
+                       FARM_MEMBER *f = ListKeyToPointer(s->FarmMemberList, id);\r
+\r
+                       t->Id = id;\r
+                       t->Controller = f->Me;\r
+                       t->Weight = f->Weight;\r
+\r
+                       LockList(f->HubList);\r
+                       {\r
+                               t->NumFarmHub = LIST_NUM(f->HubList);\r
+                               t->FarmHubs = ZeroMalloc(sizeof(RPC_FARM_HUB) * t->NumFarmHub);\r
+\r
+                               for (i = 0;i < t->NumFarmHub;i++)\r
+                               {\r
+                                       RPC_FARM_HUB *h = &t->FarmHubs[i];\r
+                                       HUB_LIST *hh = LIST_DATA(f->HubList, i);\r
+\r
+                                       h->DynamicHub = hh->DynamicHub;\r
+                                       StrCpy(h->HubName, sizeof(h->HubName), hh->Name);\r
+                               }\r
+                       }\r
+                       UnlockList(f->HubList);\r
+\r
+                       if (t->Controller)\r
+                       {\r
+                               t->ConnectedTime = TickToTime(s->Cedar->CreatedTick);\r
+                               t->Ip = 0x0100007f;\r
+                               GetMachineName(t->Hostname, sizeof(t->Hostname));\r
+                               t->Point = f->Point;\r
+\r
+                               LockList(s->ServerListenerList);\r
+                               {\r
+                                       UINT i, n;\r
+                                       t->NumPort = 0;\r
+                                       for (i = 0;i < LIST_NUM(s->ServerListenerList);i++)\r
+                                       {\r
+                                               SERVER_LISTENER *o = LIST_DATA(s->ServerListenerList, i);\r
+                                               if (o->Enabled)\r
+                                               {\r
+                                                       t->NumPort++;\r
+                                               }\r
+                                       }\r
+                                       t->Ports = ZeroMalloc(sizeof(UINT) * t->NumPort);\r
+                                       n = 0;\r
+                                       for (i = 0;i < LIST_NUM(s->ServerListenerList);i++)\r
+                                       {\r
+                                               SERVER_LISTENER *o = LIST_DATA(s->ServerListenerList, i);\r
+                                               if (o->Enabled)\r
+                                               {\r
+                                                       t->Ports[n++] = o->Port;\r
+                                               }\r
+                                       }\r
+                               }\r
+                               UnlockList(s->ServerListenerList);\r
+\r
+                               t->ServerCert = CloneX(s->Cedar->ServerX);\r
+                               t->NumSessions = Count(s->Cedar->CurrentSessions);\r
+                               t->NumTcpConnections = Count(s->Cedar->CurrentTcpConnections);\r
+                       }\r
+                       else\r
+                       {\r
+                               t->ConnectedTime = f->ConnectedTime;\r
+                               t->Ip = f->Ip;\r
+                               StrCpy(t->Hostname, sizeof(t->Hostname), f->hostname);\r
+                               t->Point = f->Point;\r
+                               t->NumPort = f->NumPort;\r
+                               t->Ports = ZeroMalloc(sizeof(UINT) * t->NumPort);\r
+                               Copy(t->Ports, f->Ports, sizeof(UINT) * t->NumPort);\r
+                               t->ServerCert = CloneX(f->ServerCert);\r
+                               t->NumSessions = f->NumSessions;\r
+                               t->NumTcpConnections = f->NumTcpConnections;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+               }\r
+       }\r
+       UnlockList(s->FarmMemberList);\r
+\r
+       return ret;\r
+}\r
+\r
+// サーバーファーム設定の取得\r
+UINT StGetFarmSetting(ADMIN *a, RPC_FARM *t)\r
+{\r
+       SERVER *s;\r
+       FreeRpcFarm(t);\r
+       Zero(t, sizeof(RPC_FARM));\r
+\r
+       s = a->Server;\r
+       t->ServerType = s->ServerType;\r
+       t->ControllerOnly = s->ControllerOnly;\r
+       t->Weight = s->Weight;\r
+\r
+       if (t->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               t->NumPort = s->NumPublicPort;\r
+               t->Ports = ZeroMalloc(sizeof(UINT) * t->NumPort);\r
+               Copy(t->Ports, s->PublicPorts, sizeof(UINT) * t->NumPort);\r
+               t->PublicIp = s->PublicIp;\r
+               StrCpy(t->ControllerName, sizeof(t->ControllerName), s->ControllerName);\r
+               t->ControllerPort = s->ControllerPort;\r
+       }\r
+       else\r
+       {\r
+               t->NumPort = 0;\r
+               t->Ports = ZeroMalloc(0);\r
+       }\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// サーバーファーム設定の設定\r
+UINT StSetFarmSetting(ADMIN *a, RPC_FARM *t)\r
+{\r
+       bool cluster_allowed = false;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+       NO_SUPPORT_FOR_BRIDGE;\r
+\r
+       cluster_allowed = GetServerCapsInt(a->Server, "b_support_cluster");\r
+\r
+       if (t->ServerType != SERVER_TYPE_STANDALONE && cluster_allowed == false)\r
+       {\r
+               // クラスタとして動作が許可されていないのにクラスタ化しようとすると\r
+               // エラーを発生する\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       ALog(a, NULL, "LA_SET_FARM_SETTING");\r
+\r
+       IncrementServerConfigRevision(a->Server);\r
+\r
+       SiSetServerType(a->Server, t->ServerType, t->PublicIp, t->NumPort, t->Ports,\r
+               t->ControllerName, t->ControllerPort, t->MemberPassword, t->Weight, t->ControllerOnly);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// パスワードの設定\r
+UINT StSetServerPassword(ADMIN *a, RPC_SET_PASSWORD *t)\r
+{\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       Copy(a->Server->HashedPassword, t->HashedPassword, SHA1_SIZE);\r
+\r
+       ALog(a, NULL, "LA_SET_SERVER_PASSWORD");\r
+\r
+       IncrementServerConfigRevision(a->Server);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// リスナーの有効化 / 無効化\r
+UINT StEnableListener(ADMIN *a, RPC_LISTENER *t)\r
+{\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       LockList(a->Server->ServerListenerList);\r
+       {\r
+               if (t->Enable)\r
+               {\r
+                       if (SiEnableListener(a->Server, t->Port) == false)\r
+                       {\r
+                               ret = ERR_LISTENER_NOT_FOUND;\r
+                       }\r
+                       else\r
+                       {\r
+                               ALog(a, NULL, "LA_ENABLE_LISTENER", t->Port);\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       if (SiDisableListener(a->Server, t->Port) == false)\r
+                       {\r
+                               ret = ERR_LISTENER_NOT_FOUND;\r
+                       }\r
+                       else\r
+                       {\r
+                               ALog(a, NULL, "LA_DISABLE_LISTENER", t->Port);\r
+                       }\r
+               }\r
+       }\r
+       UnlockList(a->Server->ServerListenerList);\r
+\r
+       IncrementServerConfigRevision(a->Server);\r
+\r
+       SleepThread(250);\r
+\r
+       return ret;\r
+}\r
+\r
+// リスナーの削除\r
+UINT StDeleteListener(ADMIN *a, RPC_LISTENER *t)\r
+{\r
+       UINT ret = ERR_NO_ERROR;\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       LockList(a->Server->ServerListenerList);\r
+       {\r
+               if (SiDeleteListener(a->Server, t->Port) == false)\r
+               {\r
+                       ret = ERR_LISTENER_NOT_FOUND;\r
+               }\r
+               else\r
+               {\r
+                       ALog(a, NULL, "LA_DELETE_LISTENER", t->Port);\r
+\r
+                       IncrementServerConfigRevision(a->Server);\r
+               }\r
+       }\r
+       UnlockList(a->Server->ServerListenerList);\r
+\r
+       return ret;\r
+}\r
+\r
+// リスナーの列挙\r
+UINT StEnumListener(ADMIN *a, RPC_LISTENER_LIST *t)\r
+{\r
+       CEDAR *c = a->Server->Cedar;\r
+       UINT i;\r
+\r
+       FreeRpcListenerList(t);\r
+       Zero(t, sizeof(RPC_LISTENER_LIST));\r
+\r
+       LockList(a->Server->ServerListenerList);\r
+       {\r
+               t->NumPort = LIST_NUM(a->Server->ServerListenerList);\r
+               t->Ports = ZeroMalloc(sizeof(UINT) * t->NumPort);\r
+               t->Enables = ZeroMalloc(sizeof(bool) * t->NumPort);\r
+               t->Errors = ZeroMalloc(sizeof(bool) * t->NumPort);\r
+\r
+               for (i = 0;i < t->NumPort;i++)\r
+               {\r
+                       SERVER_LISTENER *o = LIST_DATA(a->Server->ServerListenerList, i);\r
+\r
+                       t->Ports[i] = o->Port;\r
+                       t->Enables[i] = o->Enabled;\r
+                       if (t->Enables[i])\r
+                       {\r
+                               if (o->Listener->Status == LISTENER_STATUS_TRYING)\r
+                               {\r
+                                       t->Errors[i] = true;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       UnlockList(a->Server->ServerListenerList);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// リスナーの作成\r
+UINT StCreateListener(ADMIN *a, RPC_LISTENER *t)\r
+{\r
+       UINT ret = ERR_NO_ERROR;\r
+       CEDAR *c = a->Server->Cedar;\r
+\r
+       if (t->Port == 0 || t->Port > 65535)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       SERVER_ADMIN_ONLY;\r
+\r
+       LockList(a->Server->ServerListenerList);\r
+       {\r
+               if (SiAddListener(a->Server, t->Port, t->Enable) == false)\r
+               {\r
+                       ret = ERR_LISTENER_ALREADY_EXISTS;\r
+               }\r
+               else\r
+               {\r
+                       ALog(a, NULL, "LA_CREATE_LISTENER", t->Port);\r
+\r
+                       IncrementServerConfigRevision(a->Server);\r
+               }\r
+       }\r
+       UnlockList(a->Server->ServerListenerList);\r
+\r
+       SleepThread(250);\r
+\r
+       return ret;\r
+}\r
+\r
+// サーバー状態の取得\r
+UINT StGetServerStatus(ADMIN *a, RPC_SERVER_STATUS *t)\r
+{\r
+       CEDAR *c;\r
+       UINT i;\r
+\r
+       c = a->Server->Cedar;\r
+\r
+       Zero(t, sizeof(RPC_SERVER_STATUS));\r
+\r
+       Lock(c->TrafficLock);\r
+       {\r
+               Copy(&t->Traffic, c->Traffic, sizeof(TRAFFIC));\r
+       }\r
+       Unlock(c->TrafficLock);\r
+\r
+       GetMemInfo(&t->MemInfo);\r
+\r
+       t->ServerType = a->Server->ServerType;\r
+       t->NumTcpConnections = t->NumTcpConnectionsLocal = t->NumTcpConnectionsRemote = 0;\r
+       t->NumSessionsTotal = t->NumSessionsLocal = t->NumSessionsRemote = 0;\r
+\r
+       t->NumTcpConnectionsLocal = Count(c->CurrentTcpConnections);\r
+\r
+       if (a->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               LockList(a->Server->FarmMemberList);\r
+               {\r
+                       for (i = 0;i < LIST_NUM(a->Server->FarmMemberList);i++)\r
+                       {\r
+                               FARM_MEMBER *f = LIST_DATA(a->Server->FarmMemberList, i);\r
+\r
+                               if (f->Me == false)\r
+                               {\r
+                                       t->NumTcpConnectionsRemote += f->NumTcpConnections;\r
+                                       t->NumSessionsRemote += f->NumSessions;\r
+                                       AddTraffic(&t->Traffic, &f->Traffic);\r
+                               }\r
+                       }\r
+               }\r
+               UnlockList(a->Server->FarmMemberList);\r
+       }\r
+\r
+       t->NumMacTables = t->NumIpTables = t->NumUsers = t->NumGroups = 0;\r
+\r
+       // HUB 数の情報\r
+       LockList(c->HubList);\r
+       {\r
+               t->NumHubTotal = LIST_NUM(c->HubList);\r
+\r
+               t->NumHubStandalone = t->NumHubDynamic = t->NumHubStatic = 0;\r
+\r
+               for (i = 0;i < LIST_NUM(c->HubList);i++)\r
+               {\r
+                       HUB *h = LIST_DATA(c->HubList, i);\r
+                       Lock(h->lock);\r
+                       {\r
+                               switch (h->Type)\r
+                               {\r
+                               case HUB_TYPE_STANDALONE:\r
+                                       t->NumHubStandalone++;\r
+                                       break;\r
+\r
+                               case HUB_TYPE_FARM_STATIC:\r
+                                       t->NumHubStatic++;\r
+                                       break;\r
+\r
+                               case HUB_TYPE_FARM_DYNAMIC:\r
+                                       t->NumHubDynamic++;\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       t->NumMacTables += LIST_NUM(h->MacTable);\r
+                       t->NumIpTables += LIST_NUM(h->IpTable);\r
+\r
+                       if (h->HubDb != NULL)\r
+                       {\r
+                               t->NumUsers += LIST_NUM(h->HubDb->UserList);\r
+                               t->NumGroups += LIST_NUM(h->HubDb->GroupList);\r
+                       }\r
+\r
+                       Unlock(h->lock);\r
+               }\r
+       }\r
+       UnlockList(c->HubList);\r
+\r
+       // セッション数の情報\r
+       t->NumSessionsLocal = Count(c->CurrentSessions);\r
+       t->NumSessionsTotal = t->NumSessionsLocal + t->NumSessionsRemote;\r
+       t->NumTcpConnections = t->NumTcpConnectionsLocal + t->NumTcpConnectionsRemote;\r
+\r
+       t->AssignedBridgeLicenses = Count(c->AssignedBridgeLicense);\r
+       t->AssignedClientLicenses = Count(c->AssignedClientLicense);\r
+\r
+       t->AssignedBridgeLicensesTotal = a->Server->CurrentAssignedBridgeLicense;\r
+       t->AssignedClientLicensesTotal = a->Server->CurrentAssignedClientLicense;\r
+\r
+       t->CurrentTick = Tick64();\r
+       t->CurrentTime = SystemTime64();\r
+\r
+       t->StartTime = a->Server->StartTime;\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// サーバー情報の取得\r
+UINT StGetServerInfo(ADMIN *a, RPC_SERVER_INFO *t)\r
+{\r
+       CEDAR *c;\r
+       OS_INFO *info;\r
+       // 引数チェック\r
+       if (a == NULL || t == NULL)\r
+       {\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       FreeRpcServerInfo(t);\r
+       Zero(t, sizeof(RPC_SERVER_INFO));\r
+\r
+       c = a->Server->Cedar;\r
+\r
+       GetServerProductName(a->Server, t->ServerProductName, sizeof(t->ServerProductName));\r
+\r
+       StrCpy(t->ServerVersionString, sizeof(t->ServerVersionString), c->VerString);\r
+       StrCpy(t->ServerBuildInfoString, sizeof(t->ServerBuildInfoString), c->BuildInfo);\r
+       t->ServerVerInt = c->Version;\r
+       t->ServerBuildInt = c->Build;\r
+       GetMachineName(t->ServerHostName, sizeof(t->ServerHostName));\r
+       t->ServerType = c->Server->ServerType;\r
+\r
+       info = GetOsInfo();\r
+       if (info != NULL)\r
+       {\r
+               CopyOsInfo(&t->OsInfo, info);\r
+       }\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// OS_INFO のコピー\r
+void CopyOsInfo(OS_INFO *dst, OS_INFO *info)\r
+{\r
+       // 引数チェック\r
+       if (info == NULL || dst == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       dst->OsType = info->OsType;\r
+       dst->OsServicePack = info->OsServicePack;\r
+       dst->OsSystemName = CopyStr(info->OsSystemName);\r
+       dst->OsProductName = CopyStr(info->OsProductName);\r
+       dst->OsVendorName = CopyStr(info->OsVendorName);\r
+       dst->OsVersion = CopyStr(info->OsVersion);\r
+       dst->KernelName = CopyStr(info->KernelName);\r
+       dst->KernelVersion = CopyStr(info->KernelVersion);\r
+}\r
+\r
+// RPC_WINVER\r
+void InRpcWinVer(RPC_WINVER *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_WINVER));\r
+\r
+       t->IsWindows = PackGetBool(p, "V_IsWindows");\r
+       t->IsNT = PackGetBool(p, "V_IsNT");\r
+       t->IsServer = PackGetBool(p, "V_IsServer");\r
+       t->IsBeta = PackGetBool(p, "V_IsBeta");\r
+       t->VerMajor = PackGetInt(p, "V_VerMajor");\r
+       t->VerMinor = PackGetInt(p, "V_VerMinor");\r
+       t->Build = PackGetInt(p, "V_Build");\r
+       t->ServicePack = PackGetInt(p, "V_ServicePack");\r
+       PackGetStr(p, "V_Title", t->Title, sizeof(t->Title));\r
+}\r
+void OutRpcWinVer(PACK *p, RPC_WINVER *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddBool(p, "V_IsWindows", t->IsWindows);\r
+       PackAddBool(p, "V_IsNT", t->IsNT);\r
+       PackAddBool(p, "V_IsServer", t->IsServer);\r
+       PackAddBool(p, "V_IsBeta", t->IsBeta);\r
+       PackAddInt(p, "V_VerMajor", t->VerMajor);\r
+       PackAddInt(p, "V_VerMinor", t->VerMinor);\r
+       PackAddInt(p, "V_Build", t->Build);\r
+       PackAddInt(p, "V_ServicePack", t->ServicePack);\r
+       PackAddStr(p, "V_Title", t->Title);\r
+}\r
+\r
+// RPC_MSG\r
+void InRpcMsg(RPC_MSG *t, PACK *p)\r
+{\r
+       UINT size;\r
+       char *utf8;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_MSG));\r
+\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       size = PackGetDataSize(p, "Msg");\r
+       utf8 = ZeroMalloc(size + 8);\r
+       PackGetData(p, "Msg", utf8);\r
+       t->Msg = CopyUtfToUni(utf8);\r
+       Free(utf8);\r
+}\r
+void OutRpcMsg(PACK *p, RPC_MSG *t)\r
+{\r
+       UINT size;\r
+       char *utf8;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       utf8 = CopyUniToUtf(t->Msg);\r
+       size = StrLen(utf8);\r
+       PackAddData(p, "Msg", utf8, size);\r
+       Free(utf8);\r
+}\r
+void FreeRpcMsg(RPC_MSG *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Msg);\r
+}\r
+\r
+// RPC_ENUM_ETH_VLAN\r
+void InRpcEnumEthVLan(RPC_ENUM_ETH_VLAN *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_ETH_VLAN));\r
+\r
+       t->NumItem = PackGetIndexCount(p, "DeviceName");\r
+       t->Items = ZeroMalloc(sizeof(RPC_ENUM_ETH_VLAN_ITEM) * t->NumItem);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_ENUM_ETH_VLAN_ITEM *e = &t->Items[i];\r
+\r
+               PackGetStrEx(p, "DeviceName", e->DeviceName, sizeof(e->DeviceName), i);\r
+               PackGetStrEx(p, "Guid", e->Guid, sizeof(e->Guid), i);\r
+               PackGetStrEx(p, "DeviceInstanceId", e->DeviceInstanceId, sizeof(e->DeviceInstanceId), i);\r
+               PackGetStrEx(p, "DriverName", e->DriverName, sizeof(e->DriverName), i);\r
+               PackGetStrEx(p, "DriverType", e->DriverType, sizeof(e->DriverType), i);\r
+               e->Support = PackGetBoolEx(p, "Support", i);\r
+               e->Enabled = PackGetBoolEx(p, "Enabled", i);\r
+       }\r
+}\r
+void OutRpcEnumEthVLan(PACK *p, RPC_ENUM_ETH_VLAN *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_ENUM_ETH_VLAN_ITEM *e = &t->Items[i];\r
+\r
+               PackAddStrEx(p, "DeviceName", e->DeviceName, i, t->NumItem);\r
+               PackAddStrEx(p, "Guid", e->Guid, i, t->NumItem);\r
+               PackAddStrEx(p, "DeviceInstanceId", e->DeviceInstanceId, i, t->NumItem);\r
+               PackAddStrEx(p, "DriverName", e->DriverName, i, t->NumItem);\r
+               PackAddStrEx(p, "DriverType", e->DriverType, i, t->NumItem);\r
+               PackAddBoolEx(p, "Support", e->Support, i, t->NumItem);\r
+               PackAddBoolEx(p, "Enabled", e->Enabled, i, t->NumItem);\r
+       }\r
+}\r
+void FreeRpcEnumEthVLan(RPC_ENUM_ETH_VLAN *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Items);\r
+}\r
+\r
+// RPC_ENUM_LOG_FILE\r
+void InRpcEnumLogFile(RPC_ENUM_LOG_FILE *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_LOG_FILE));\r
+       t->NumItem = PackGetInt(p, "NumItem");\r
+       t->Items = ZeroMalloc(sizeof(RPC_ENUM_LOG_FILE_ITEM) * t->NumItem);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_ENUM_LOG_FILE_ITEM *e = &t->Items[i];\r
+\r
+               PackGetStrEx(p, "FilePath", e->FilePath, sizeof(e->FilePath), i);\r
+               PackGetStrEx(p, "ServerName", e->ServerName, sizeof(e->ServerName), i);\r
+               e->FileSize = PackGetIntEx(p, "FileSize", i);\r
+               e->UpdatedTime = PackGetInt64Ex(p, "UpdatedTime", i);\r
+       }\r
+}\r
+void OutRpcEnumLogFile(PACK *p, RPC_ENUM_LOG_FILE *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "NumItem", t->NumItem);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_ENUM_LOG_FILE_ITEM *e = &t->Items[i];\r
+\r
+               PackAddStrEx(p, "FilePath", e->FilePath, i, t->NumItem);\r
+               PackAddStrEx(p, "ServerName", e->ServerName, i, t->NumItem);\r
+               PackAddIntEx(p, "FileSize", e->FileSize, i, t->NumItem);\r
+               PackAddInt64Ex(p, "UpdatedTime", e->UpdatedTime, i, t->NumItem);\r
+       }\r
+}\r
+void FreeRpcEnumLogFile(RPC_ENUM_LOG_FILE *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Items);\r
+}\r
+void AdjoinRpcEnumLogFile(RPC_ENUM_LOG_FILE *t, RPC_ENUM_LOG_FILE *src)\r
+{\r
+       LIST *o;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || src == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       o = NewListFast(CmpLogFile);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_ENUM_LOG_FILE_ITEM *e = &t->Items[i];\r
+               LOG_FILE *f = ZeroMalloc(sizeof(LOG_FILE));\r
+\r
+               f->FileSize = e->FileSize;\r
+               StrCpy(f->Path, sizeof(f->Path), e->FilePath);\r
+               StrCpy(f->ServerName, sizeof(f->ServerName), e->ServerName);\r
+               f->UpdatedTime = e->UpdatedTime;\r
+\r
+               Add(o, f);\r
+       }\r
+\r
+       for (i = 0;i < src->NumItem;i++)\r
+       {\r
+               RPC_ENUM_LOG_FILE_ITEM *e = &src->Items[i];\r
+               LOG_FILE *f = ZeroMalloc(sizeof(LOG_FILE));\r
+\r
+               f->FileSize = e->FileSize;\r
+               StrCpy(f->Path, sizeof(f->Path), e->FilePath);\r
+               StrCpy(f->ServerName, sizeof(f->ServerName), e->ServerName);\r
+               f->UpdatedTime = e->UpdatedTime;\r
+\r
+               Add(o, f);\r
+       }\r
+\r
+       FreeRpcEnumLogFile(t);\r
+\r
+       Sort(o);\r
+\r
+       Zero(t, sizeof(RPC_ENUM_LOG_FILE));\r
+       t->NumItem = LIST_NUM(o);\r
+       t->Items = ZeroMalloc(sizeof(RPC_ENUM_LOG_FILE_ITEM) * t->NumItem);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               LOG_FILE *f = LIST_DATA(o, i);\r
+               RPC_ENUM_LOG_FILE_ITEM *e = &t->Items[i];\r
+\r
+               StrCpy(e->FilePath, sizeof(e->FilePath), f->Path);\r
+               StrCpy(e->ServerName, sizeof(e->ServerName), f->ServerName);\r
+               e->FileSize = f->FileSize;\r
+               e->UpdatedTime = f->UpdatedTime;\r
+       }\r
+\r
+       FreeEnumLogFile(o);\r
+}\r
+\r
+// RPC_READ_LOG_FILE\r
+void InRpcReadLogFile(RPC_READ_LOG_FILE *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_READ_LOG_FILE));\r
+       PackGetStr(p, "FilePath", t->FilePath, sizeof(t->FilePath));\r
+       PackGetStr(p, "ServerName", t->ServerName, sizeof(t->ServerName));\r
+       t->Offset = PackGetInt(p, "Offset");\r
+\r
+       t->Buffer = PackGetBuf(p, "Buffer");\r
+}\r
+void OutRpcReadLogFile(PACK *p, RPC_READ_LOG_FILE *t)\r
+{\r
+       // 引数チェック\r
+       if (p == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "FilePath", t->FilePath);\r
+       PackAddStr(p, "ServerName", t->ServerName);\r
+       PackAddInt(p, "Offset", t->Offset);\r
+\r
+       if (t->Buffer != NULL)\r
+       {\r
+               PackAddBuf(p, "Buffer", t->Buffer);\r
+       }\r
+}\r
+void FreeRpcReadLogFile(RPC_READ_LOG_FILE *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (t->Buffer != NULL)\r
+       {\r
+               FreeBuf(t->Buffer);\r
+       }\r
+}\r
+\r
+// RPC_AC_LIST\r
+void InRpcAcList(RPC_AC_LIST *t, PACK *p)\r
+{\r
+       UINT i;\r
+       LIST *o;\r
+       UINT num;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_AC_LIST));\r
+       o = NewAcList();\r
+\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       num = PackGetInt(p, "NumItem");\r
+\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               AC *ac = ZeroMalloc(sizeof(AC));\r
+\r
+               ac->Deny = PackGetBoolEx(p, "Deny", i);\r
+               PackGetIpEx(p, "IpAddress", &ac->IpAddress, i);\r
+               ac->Masked = PackGetBoolEx(p, "Masked", i);\r
+\r
+               if (ac->Masked)\r
+               {\r
+                       PackGetIpEx(p, "SubnetMask", &ac->SubnetMask, i);\r
+               }\r
+\r
+               PackGetIntEx(p, "testtest", i);\r
+\r
+               ac->Priority = PackGetIntEx(p, "Priority", i);\r
+\r
+               AddAc(o, ac);\r
+\r
+               Free(ac);\r
+       }\r
+\r
+       t->o = o;\r
+}\r
+void OutRpcAcList(PACK *p, RPC_AC_LIST *t)\r
+{\r
+       UINT i, num;\r
+       LIST *o;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       o = t->o;\r
+       num = LIST_NUM(o);\r
+\r
+       PackAddInt(p, "NumItem", num);\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               AC *ac = LIST_DATA(o, i);\r
+\r
+               PackAddBoolEx(p, "Deny", ac->Deny, i, num);\r
+               PackAddIpEx(p, "IpAddress", &ac->IpAddress, i, num);\r
+               PackAddBoolEx(p, "Masked", ac->Masked, i, num);\r
+\r
+               PackAddIpEx(p, "SubnetMask", &ac->SubnetMask, i, num);\r
+\r
+               PackAddIntEx(p, "Priority", ac->Priority, i, num);\r
+       }\r
+}\r
+void FreeRpcAcList(RPC_AC_LIST *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       FreeAcList(t->o);\r
+}\r
+\r
+// RPC_INT\r
+void InRpcInt(RPC_INT *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_INT));\r
+       t->IntValue = PackGetInt(p, "IntValue");\r
+}\r
+void OutRpcInt(PACK *p, RPC_INT *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "IntValue", t->IntValue);\r
+}\r
+\r
+// RPC_ENUM_CRL\r
+void InRpcEnumCrl(RPC_ENUM_CRL *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_CRL));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->NumItem = PackGetInt(p, "NumItem");\r
+\r
+       t->Items = ZeroMalloc(sizeof(RPC_ENUM_CRL_ITEM) * t->NumItem);\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_ENUM_CRL_ITEM *e = &t->Items[i];\r
+\r
+               e->Key = PackGetIntEx(p, "Key", i);\r
+               PackGetUniStrEx(p, "CrlInfo", e->CrlInfo, sizeof(e->CrlInfo), i);\r
+       }\r
+}\r
+void OutRpcEnumCrl(PACK *p, RPC_ENUM_CRL *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddInt(p, "NumItem", t->NumItem);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_ENUM_CRL_ITEM *e = &t->Items[i];\r
+\r
+               PackAddIntEx(p, "Key", e->Key, i, t->NumItem);\r
+               PackAddUniStrEx(p, "CrlInfo", e->CrlInfo, i, t->NumItem);\r
+       }\r
+}\r
+void FreeRpcEnumCrl(RPC_ENUM_CRL *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Items);\r
+}\r
+\r
+// RPC_CRL\r
+void InRpcCrl(RPC_CRL *t, PACK *p)\r
+{\r
+       BUF *b;\r
+       NAME *n;\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_CRL));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->Key = PackGetInt(p, "Key");\r
+       b = PackGetBuf(p, "Serial");\r
+       t->Crl = ZeroMalloc(sizeof(CRL));\r
+       if (b != NULL)\r
+       {\r
+               t->Crl->Serial = NewXSerial(b->Buf, b->Size);\r
+               FreeBuf(b);\r
+       }\r
+       t->Crl->Name = ZeroMalloc(sizeof(NAME));\r
+       n = t->Crl->Name;\r
+       if (PackGetUniStr(p, "CommonName", tmp, sizeof(tmp)))\r
+       {\r
+               n->CommonName = CopyUniStr(tmp);\r
+       }\r
+       if (PackGetUniStr(p, "Organization", tmp, sizeof(tmp)))\r
+       {\r
+               n->Organization = CopyUniStr(tmp);\r
+       }\r
+       if (PackGetUniStr(p, "Unit", tmp, sizeof(tmp)))\r
+       {\r
+               n->Unit = CopyUniStr(tmp);\r
+       }\r
+       if (PackGetUniStr(p, "Country", tmp, sizeof(tmp)))\r
+       {\r
+               n->Country = CopyUniStr(tmp);\r
+       }\r
+       if (PackGetUniStr(p, "State", tmp, sizeof(tmp)))\r
+       {\r
+               n->State = CopyUniStr(tmp);\r
+       }\r
+       if (PackGetUniStr(p, "Local", tmp, sizeof(tmp)))\r
+       {\r
+               n->Local = CopyUniStr(tmp);\r
+       }\r
+       if (PackGetDataSize(p, "DigestMD5") == MD5_SIZE)\r
+       {\r
+               PackGetData(p, "DigestMD5", t->Crl->DigestMD5);\r
+       }\r
+       if (PackGetDataSize(p, "DigestSHA1") == SHA1_SIZE)\r
+       {\r
+               PackGetData(p, "DigestSHA1", t->Crl->DigestSHA1);\r
+       }\r
+}\r
+void OutRpcCrl(PACK *p, RPC_CRL *t)\r
+{\r
+       NAME *n;\r
+       // 引数チェック\r
+       if (p == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddInt(p, "Key", t->Key);\r
+\r
+       if (t->Crl == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (t->Crl->Serial != NULL)\r
+       {\r
+               PackAddData(p, "Serial", t->Crl->Serial->data, t->Crl->Serial->size);\r
+       }\r
+       n = t->Crl->Name;\r
+       if (n->CommonName != NULL)\r
+       {\r
+               PackAddUniStr(p, "CommonName", n->CommonName);\r
+       }\r
+       if (n->Organization != NULL)\r
+       {\r
+               PackAddUniStr(p, "Organization", n->Organization);\r
+       }\r
+       if (n->Unit != NULL)\r
+       {\r
+               PackAddUniStr(p, "Unit", n->Unit);\r
+       }\r
+       if (n->Country != NULL)\r
+       {\r
+               PackAddUniStr(p, "Country", n->Country);\r
+       }\r
+       if (n->State != NULL)\r
+       {\r
+               PackAddUniStr(p, "State", n->State);\r
+       }\r
+       if (n->Local != NULL)\r
+       {\r
+               PackAddUniStr(p, "Local", n->Local);\r
+       }\r
+       if (IsZero(t->Crl->DigestMD5, MD5_SIZE) == false)\r
+       {\r
+               PackAddData(p, "DigestMD5", t->Crl->DigestMD5, MD5_SIZE);\r
+       }\r
+       if (IsZero(t->Crl->DigestSHA1, SHA1_SIZE) == false)\r
+       {\r
+               PackAddData(p, "DigestSHA1", t->Crl->DigestSHA1, SHA1_SIZE);\r
+       }\r
+}\r
+void FreeRpcCrl(RPC_CRL *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       FreeCrl(t->Crl);\r
+}\r
+\r
+// RPC_ENUM_L3TABLE\r
+void InRpcEnumL3Table(RPC_ENUM_L3TABLE *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_L3TABLE));\r
+       t->NumItem = PackGetInt(p, "NumItem");\r
+       PackGetStr(p, "Name", t->Name, sizeof(t->Name));\r
+       t->Items = ZeroMalloc(sizeof(RPC_L3TABLE) * t->NumItem);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_L3TABLE *e = &t->Items[i];\r
+\r
+               e->NetworkAddress = PackGetIp32Ex(p, "NetworkAddress", i);\r
+               e->SubnetMask = PackGetIp32Ex(p, "SubnetMask", i);\r
+               e->GatewayAddress = PackGetIp32Ex(p, "GatewayAddress", i);\r
+               e->Metric = PackGetIntEx(p, "Metric", i);\r
+       }\r
+}\r
+void OutRpcEnumL3Table(PACK *p, RPC_ENUM_L3TABLE *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (p == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "NumItem", t->NumItem);\r
+       PackAddStr(p, "Name", t->Name);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_L3TABLE *e = &t->Items[i];\r
+\r
+               PackAddIp32Ex(p, "NetworkAddress", e->NetworkAddress, i, t->NumItem);\r
+               PackAddIp32Ex(p, "SubnetMask", e->SubnetMask, i, t->NumItem);\r
+               PackAddIp32Ex(p, "GatewayAddress", e->GatewayAddress, i, t->NumItem);\r
+               PackAddIntEx(p, "Metric", e->Metric, i, t->NumItem);\r
+       }\r
+}\r
+void FreeRpcEnumL3Table(RPC_ENUM_L3TABLE *t)\r
+{\r
+       Free(t->Items);\r
+}\r
+\r
+// RPC_L3TABLE\r
+void InRpcL3Table(RPC_L3TABLE *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_L3TABLE));\r
+       PackGetStr(p, "Name", t->Name, sizeof(t->Name));\r
+       t->NetworkAddress = PackGetIp32(p, "NetworkAddress");\r
+       t->SubnetMask = PackGetIp32(p, "SubnetMask");\r
+       t->GatewayAddress = PackGetIp32(p, "GatewayAddress");\r
+       t->Metric = PackGetInt(p, "Metric");\r
+}\r
+void OutRpcL3Table(PACK *p, RPC_L3TABLE *t)\r
+{\r
+       // 引数チェック\r
+       if (p == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "Name", t->Name);\r
+       PackAddIp32(p, "NetworkAddress", t->NetworkAddress);\r
+       PackAddIp32(p, "SubnetMask", t->SubnetMask);\r
+       PackAddIp32(p, "GatewayAddress", t->GatewayAddress);\r
+       PackAddInt(p, "Metric", t->Metric);\r
+}\r
+\r
+// RPC_ENUM_L3IF\r
+void InRpcEnumL3If(RPC_ENUM_L3IF *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_L3IF));\r
+       t->NumItem = PackGetInt(p, "NumItem");\r
+       PackGetStr(p, "Name", t->Name, sizeof(t->Name));\r
+       t->Items = ZeroMalloc(sizeof(RPC_L3IF) * t->NumItem);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_L3IF *f = &t->Items[i];\r
+\r
+               PackGetStrEx(p, "HubName", f->HubName, sizeof(f->HubName), i);\r
+               f->IpAddress = PackGetIp32Ex(p, "IpAddress", i);\r
+               f->SubnetMask = PackGetIp32Ex(p, "SubnetMask", i);\r
+       }\r
+}\r
+void OutRpcEnumL3If(PACK *p, RPC_ENUM_L3IF *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (p == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "NumItem", t->NumItem);\r
+       PackAddStr(p, "Name", t->Name);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_L3IF *f = &t->Items[i];\r
+\r
+               PackAddStrEx(p, "HubName", f->HubName, i, t->NumItem);\r
+               PackAddIp32Ex(p, "IpAddress", f->IpAddress, i, t->NumItem);\r
+               PackAddIp32Ex(p, "SubnetMask", f->SubnetMask, i, t->NumItem);\r
+       }\r
+}\r
+void FreeRpcEnumL3If(RPC_ENUM_L3IF *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Items);\r
+}\r
+\r
+// RPC_L3IF\r
+void InRpcL3If(RPC_L3IF *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_L3IF));\r
+       PackGetStr(p, "Name", t->Name, sizeof(t->Name));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->IpAddress = PackGetIp32(p, "IpAddress");\r
+       t->SubnetMask = PackGetIp32(p, "SubnetMask");\r
+}\r
+void OutRpcL3If(PACK *p, RPC_L3IF *t)\r
+{\r
+       // 引数チェック\r
+       if (p == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "Name", t->Name);\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddIp32(p, "IpAddress", t->IpAddress);\r
+       PackAddIp32(p, "SubnetMask", t->SubnetMask);\r
+}\r
+\r
+// RPC_L3SW\r
+void InRpcL3Sw(RPC_L3SW *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_L3SW));\r
+       PackGetStr(p, "Name", t->Name, sizeof(t->Name));\r
+}\r
+void OutRpcL3Sw(PACK *p, RPC_L3SW *t)\r
+{\r
+       // 引数チェック\r
+       if (p == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "Name", t->Name);\r
+}\r
+\r
+// RPC_ENUM_L3SW\r
+void InRpcEnumL3Sw(RPC_ENUM_L3SW *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_L3SW));\r
+       t->NumItem = PackGetInt(p, "NumItem");\r
+       t->Items = ZeroMalloc(sizeof(RPC_ENUM_L3SW_ITEM) * t->NumItem);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_ENUM_L3SW_ITEM *s = &t->Items[i];\r
+\r
+               PackGetStrEx(p, "Name", s->Name, sizeof(s->Name), i);\r
+               s->NumInterfaces = PackGetIntEx(p, "NumInterfaces", i);\r
+               s->NumTables = PackGetIntEx(p, "NumTables", i);\r
+               s->Active = PackGetBoolEx(p, "Active", i);\r
+               s->Online = PackGetBoolEx(p, "Online", i);\r
+       }\r
+}\r
+void OutRpcEnumL3Sw(PACK *p, RPC_ENUM_L3SW *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (p == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "NumItem", t->NumItem);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_ENUM_L3SW_ITEM *s = &t->Items[i];\r
+\r
+               PackAddStrEx(p, "Name", s->Name, i, t->NumItem);\r
+               PackAddIntEx(p, "NumInterfaces", s->NumInterfaces, i, t->NumItem);\r
+               PackAddIntEx(p, "NumTables", s->NumTables, i, t->NumItem);\r
+               PackAddBoolEx(p, "Active", s->Active, i, t->NumItem);\r
+               PackAddBoolEx(p, "Online", s->Online, i, t->NumItem);\r
+       }\r
+}\r
+void FreeRpcEnumL3Sw(RPC_ENUM_L3SW *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Items);\r
+}\r
+\r
+// RPC_ENUM_ETH\r
+void InRpcEnumEth(RPC_ENUM_ETH *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_ETH));\r
+       t->NumItem = PackGetInt(p, "NumItem");\r
+       t->Items = ZeroMalloc(sizeof(RPC_ENUM_ETH_ITEM) * t->NumItem);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_ENUM_ETH_ITEM *e = &t->Items[i];\r
+               PackGetStrEx(p, "DeviceName", e->DeviceName, sizeof(e->DeviceName), i);\r
+               PackGetUniStrEx(p, "NetworkConnectionName", e->NetworkConnectionName, sizeof(e->NetworkConnectionName), i);\r
+       }\r
+}\r
+void OutRpcEnumEth(PACK *p, RPC_ENUM_ETH *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (p == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "NumItem", t->NumItem);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_ENUM_ETH_ITEM *e = &t->Items[i];\r
+               PackAddStrEx(p, "DeviceName", e->DeviceName, i, t->NumItem);\r
+               PackAddUniStrEx(p, "NetworkConnectionName", e->NetworkConnectionName, i, t->NumItem);\r
+       }\r
+}\r
+void FreeRpcEnumEth(RPC_ENUM_ETH *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Items);\r
+}\r
+\r
+// RPC_LOCALBRIDGE\r
+void InRpcLocalBridge(RPC_LOCALBRIDGE *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_LOCALBRIDGE));\r
+       PackGetStr(p, "DeviceName", t->DeviceName, sizeof(t->DeviceName));\r
+       PackGetStr(p, "HubNameLB", t->HubName, sizeof(t->HubName));\r
+       t->TapMode = PackGetBool(p, "TapMode");\r
+}\r
+void OutRpcLocalBridge(PACK *p, RPC_LOCALBRIDGE *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "DeviceName", t->DeviceName);\r
+       PackAddStr(p, "HubNameLB", t->HubName);\r
+       PackAddBool(p, "TapMode", t->TapMode);\r
+}\r
+\r
+// RPC_ENUM_LOCALBRIDGE\r
+void InRpcEnumLocalBridge(RPC_ENUM_LOCALBRIDGE *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_LOCALBRIDGE));\r
+       t->NumItem = PackGetInt(p, "NumItem");\r
+       t->Items = ZeroMalloc(sizeof(RPC_LOCALBRIDGE) * t->NumItem);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_LOCALBRIDGE *e = &t->Items[i];\r
+\r
+               PackGetStrEx(p, "DeviceName", e->DeviceName, sizeof(e->DeviceName), i);\r
+               PackGetStrEx(p, "HubNameLB", e->HubName, sizeof(e->HubName), i);\r
+               e->Online = PackGetBoolEx(p, "Online", i);\r
+               e->Active = PackGetBoolEx(p, "Active", i);\r
+               e->TapMode = PackGetBoolEx(p, "TapMode", i);\r
+       }\r
+}\r
+void OutRpcEnumLocalBridge(PACK *p, RPC_ENUM_LOCALBRIDGE *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "NumItem", t->NumItem);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_LOCALBRIDGE *e = &t->Items[i];\r
+\r
+               PackAddStrEx(p, "DeviceName", e->DeviceName, i, t->NumItem);\r
+               PackAddStrEx(p, "HubNameLB", e->HubName, i, t->NumItem);\r
+               PackAddBoolEx(p, "Online", e->Online, i, t->NumItem);\r
+               PackAddBoolEx(p, "Active", e->Active, i, t->NumItem);\r
+               PackAddBoolEx(p, "TapMode", e->TapMode, i, t->NumItem);\r
+       }\r
+}\r
+void FreeRpcEnumLocalBridge(RPC_ENUM_LOCALBRIDGE *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+       Free(t->Items);\r
+}\r
+\r
+// MEMINFO\r
+void InRpcMemInfo(MEMINFO *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(MEMINFO));\r
+       t->TotalMemory = PackGetInt64(p, "TotalMemory");\r
+       t->UsedMemory = PackGetInt64(p, "UsedMemory");\r
+       t->FreeMemory = PackGetInt64(p, "FreeMemory");\r
+       t->TotalPhys = PackGetInt64(p, "TotalPhys");\r
+       t->UsedPhys = PackGetInt64(p, "UsedPhys");\r
+       t->FreePhys = PackGetInt64(p, "FreePhys");\r
+}\r
+void OutRpcMemInfo(PACK *p, MEMINFO *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt64(p, "TotalMemory", t->TotalMemory);\r
+       PackAddInt64(p, "UsedMemory", t->UsedMemory);\r
+       PackAddInt64(p, "FreeMemory", t->FreeMemory);\r
+       PackAddInt64(p, "TotalPhys", t->TotalPhys);\r
+       PackAddInt64(p, "UsedPhys", t->UsedPhys);\r
+       PackAddInt64(p, "FreePhys", t->FreePhys);\r
+}\r
+\r
+// OS_INFO\r
+void InRpcOsInfo(OS_INFO *t, PACK *p)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(OS_INFO));\r
+       t->OsType = PackGetInt(p, "OsType");\r
+       t->OsServicePack = PackGetInt(p, "OsServicePack");\r
+       if (PackGetStr(p, "OsSystemName", tmp, sizeof(tmp)))\r
+       {\r
+               t->OsSystemName = CopyStr(tmp);\r
+       }\r
+       if (PackGetStr(p, "OsProductName", tmp, sizeof(tmp)))\r
+       {\r
+               t->OsProductName = CopyStr(tmp);\r
+       }\r
+       if (PackGetStr(p, "OsVendorName", tmp, sizeof(tmp)))\r
+       {\r
+               t->OsVendorName = CopyStr(tmp);\r
+       }\r
+       if (PackGetStr(p, "OsVersion", tmp, sizeof(tmp)))\r
+       {\r
+               t->OsVersion = CopyStr(tmp);\r
+       }\r
+       if (PackGetStr(p, "KernelName", tmp, sizeof(tmp)))\r
+       {\r
+               t->KernelName = CopyStr(tmp);\r
+       }\r
+       if (PackGetStr(p, "KernelVersion", tmp, sizeof(tmp)))\r
+       {\r
+               t->KernelVersion = CopyStr(tmp);\r
+       }\r
+}\r
+void OutRpcOsInfo(PACK *p, OS_INFO *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "OsType", t->OsType);\r
+       PackAddInt(p, "OsServicePack", t->OsServicePack);\r
+       PackAddStr(p, "OsSystemName", t->OsSystemName);\r
+       PackAddStr(p, "OsProductName", t->OsProductName);\r
+       PackAddStr(p, "OsVendorName", t->OsVendorName);\r
+       PackAddStr(p, "OsVersion", t->OsVersion);\r
+       PackAddStr(p, "KernelName", t->KernelName);\r
+       PackAddStr(p, "KernelVersion", t->KernelVersion);\r
+}\r
+void FreeRpcOsInfo(OS_INFO *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->OsSystemName);\r
+       Free(t->OsProductName);\r
+       Free(t->OsVendorName);\r
+       Free(t->OsVersion);\r
+       Free(t->KernelName);\r
+       Free(t->KernelVersion);\r
+}\r
+\r
+// ローカルのログファイルを読み込む\r
+void SiReadLocalLogFile(SERVER *s, char *filepath, UINT offset, RPC_READ_LOG_FILE *t)\r
+{\r
+       char exe_dir[MAX_PATH], full_path[MAX_PATH];\r
+       IO *o;\r
+       // 引数チェック\r
+       if (s == NULL || t == NULL || filepath == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_READ_LOG_FILE));\r
+\r
+       GetExeDir(exe_dir, sizeof(exe_dir));\r
+       Format(full_path, sizeof(full_path), "%s/%s", exe_dir, filepath);\r
+\r
+       // ファイルを読み込む\r
+       o = FileOpenEx(full_path, false, false);\r
+       if (o != NULL)\r
+       {\r
+               UINT filesize = FileSize(o);\r
+\r
+               if (offset < filesize)\r
+               {\r
+                       UINT readsize = MIN(filesize - offset, FTP_BLOCK_SIZE);\r
+                       void *buf = ZeroMalloc(readsize);\r
+\r
+                       FileSeek(o, FILE_BEGIN, offset);\r
+                       FileRead(o, buf, readsize);\r
+\r
+                       t->Buffer = NewBuf();\r
+                       WriteBuf(t->Buffer, buf, readsize);\r
+                       Free(buf);\r
+               }\r
+\r
+               FileClose(o);\r
+       }\r
+}\r
+\r
+// ローカルのログファイルを列挙する\r
+void SiEnumLocalLogFileList(SERVER *s, char *hubname, RPC_ENUM_LOG_FILE *t)\r
+{\r
+       LIST *o;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (s == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_LOG_FILE));\r
+\r
+       o = EnumLogFile(hubname);\r
+\r
+       t->NumItem = LIST_NUM(o);\r
+       t->Items = ZeroMalloc(sizeof(RPC_ENUM_LOG_FILE_ITEM) * t->NumItem);\r
+\r
+       for (i = 0;i < LIST_NUM(o);i++)\r
+       {\r
+               LOG_FILE *f = LIST_DATA(o, i);\r
+               RPC_ENUM_LOG_FILE_ITEM *e = &t->Items[i];\r
+\r
+               StrCpy(e->FilePath, sizeof(e->FilePath), f->Path);\r
+               StrCpy(e->ServerName, sizeof(e->ServerName), f->ServerName);\r
+               e->FileSize = f->FileSize;\r
+               e->UpdatedTime = f->UpdatedTime;\r
+       }\r
+\r
+       FreeEnumLogFile(o);\r
+}\r
+\r
+// ローカルのセッションを列挙する\r
+void SiEnumLocalSession(SERVER *s, char *hubname, RPC_ENUM_SESSION *t)\r
+{\r
+       HUB *h;\r
+       // 引数チェック\r
+       if (s == NULL || hubname == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       LockHubList(s->Cedar);\r
+       h = GetHub(s->Cedar, hubname);\r
+       UnlockHubList(s->Cedar);\r
+\r
+       if (h == NULL)\r
+       {\r
+               t->NumSession = 0;\r
+               t->Sessions = ZeroMalloc(0);\r
+               return;\r
+       }\r
+\r
+       LockList(h->SessionList);\r
+       {\r
+               UINT i;\r
+               t->NumSession = LIST_NUM(h->SessionList);\r
+               t->Sessions = ZeroMalloc(sizeof(RPC_ENUM_SESSION_ITEM) * t->NumSession);\r
+\r
+               for (i = 0;i < t->NumSession;i++)\r
+               {\r
+                       SESSION *s = LIST_DATA(h->SessionList, i);\r
+                       RPC_ENUM_SESSION_ITEM *e = &t->Sessions[i];\r
+                       Lock(s->lock);\r
+                       {\r
+                               StrCpy(e->Name, sizeof(e->Name), s->Name);\r
+                               StrCpy(e->Username, sizeof(e->Username), s->Username);\r
+                               e->Ip = IPToUINT(&s->Connection->ClientIp);\r
+                               StrCpy(e->Hostname, sizeof(e->Hostname), s->Connection->ClientHostname);\r
+                               e->MaxNumTcp = s->MaxConnection;\r
+                               e->LinkMode = s->LinkModeServer;\r
+                               e->SecureNATMode = s->SecureNATMode;\r
+                               e->BridgeMode = s->BridgeMode;\r
+                               e->Layer3Mode = s->L3SwitchMode;\r
+                               e->VLanId = s->VLanId;\r
+                               LockList(s->Connection->Tcp->TcpSockList);\r
+                               {\r
+                                       e->CurrentNumTcp = s->Connection->Tcp->TcpSockList->num_item;\r
+                               }\r
+                               UnlockList(s->Connection->Tcp->TcpSockList);\r
+                               Lock(s->TrafficLock);\r
+                               {\r
+                                       e->PacketSize = GetTrafficPacketSize(s->Traffic);\r
+                                       e->PacketNum = GetTrafficPacketNum(s->Traffic);\r
+                               }\r
+                               Unlock(s->TrafficLock);\r
+                               e->Client_BridgeMode = s->IsBridgeMode;\r
+                               e->Client_MonitorMode = s->IsMonitorMode;\r
+                               Copy(e->UniqueId, s->NodeInfo.UniqueId, 16);\r
+                       }\r
+                       Unlock(s->lock);\r
+                       GetMachineName(e->RemoteHostname, sizeof(e->RemoteHostname));\r
+               }\r
+       }\r
+       UnlockList(h->SessionList);\r
+\r
+       ReleaseHub(h);\r
+}\r
+\r
+// RPC_ENUM_LICENSE_KEY\r
+void InRpcEnumLicenseKey(RPC_ENUM_LICENSE_KEY *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_LICENSE_KEY));\r
+       t->NumItem = PackGetInt(p, "NumItem");\r
+       t->Items = ZeroMalloc(sizeof(RPC_ENUM_LICENSE_KEY_ITEM) * t->NumItem);\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_ENUM_LICENSE_KEY_ITEM *e = &t->Items[i];\r
+\r
+               e->Id = PackGetIntEx(p, "Id", i);\r
+               PackGetStrEx(p, "LicenseKey", e->LicenseKey, sizeof(e->LicenseKey), i);\r
+               PackGetStrEx(p, "LicenseId", e->LicenseId, sizeof(e->LicenseId), i);\r
+               PackGetStrEx(p, "LicenseName", e->LicenseName, sizeof(e->LicenseName), i);\r
+               e->Expires = PackGetInt64Ex(p, "Expires", i);\r
+               e->Status = PackGetIntEx(p, "Status", i);\r
+               e->ProductId = PackGetIntEx(p, "ProductId", i);\r
+               e->SystemId = PackGetInt64Ex(p, "SystemId", i);\r
+               e->SerialId = PackGetIntEx(p, "SerialId", i);\r
+       }\r
+}\r
+void OutRpcEnumLicenseKey(PACK *p, RPC_ENUM_LICENSE_KEY *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "NumItem", t->NumItem);\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               RPC_ENUM_LICENSE_KEY_ITEM *e = &t->Items[i];\r
+\r
+               PackAddIntEx(p, "Id", e->Id, i, t->NumItem);\r
+               PackAddStrEx(p, "LicenseKey", e->LicenseKey, i, t->NumItem);\r
+               PackAddStrEx(p, "LicenseId", e->LicenseId, i, t->NumItem);\r
+               PackAddStrEx(p, "LicenseName", e->LicenseName, i, t->NumItem);\r
+               PackAddInt64Ex(p, "Expires", e->Expires, i, t->NumItem);\r
+               PackAddIntEx(p, "Status", e->Status, i, t->NumItem);\r
+               PackAddIntEx(p, "ProductId", e->ProductId, i, t->NumItem);\r
+               PackAddInt64Ex(p, "SystemId", e->SystemId, i, t->NumItem);\r
+               PackAddIntEx(p, "SerialId", e->SerialId, i, t->NumItem);\r
+       }\r
+}\r
+void FreeRpcEnumLicenseKey(RPC_ENUM_LICENSE_KEY *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Items);\r
+}\r
+\r
+// RPC_LICENSE_STATUS\r
+void InRpcLicenseStatus(RPC_LICENSE_STATUS *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_LICENSE_STATUS));\r
+\r
+       t->EditionId = PackGetInt(p, "EditionId");\r
+       PackGetStr(p, "EditionStr", t->EditionStr, sizeof(t->EditionStr) );\r
+       t->SystemId = PackGetInt64(p, "SystemId");\r
+       t->SystemExpires = PackGetInt64(p, "SystemExpires");\r
+       t->NumClientConnectLicense = PackGetInt(p, "NumClientConnectLicense");\r
+       t->NumBridgeConnectLicense = PackGetInt(p, "NumBridgeConnectLicense");\r
+\r
+       // v3.0\r
+       t->NeedSubscription = PackGetBool(p, "NeedSubscription");\r
+       t->AllowEnterpriseFunction = PackGetBool(p, "AllowEnterpriseFunction");\r
+       t->SubscriptionExpires = PackGetInt64(p, "SubscriptionExpires");\r
+       t->IsSubscriptionExpired = PackGetBool(p, "IsSubscriptionExpired");\r
+       t->NumUserCreationLicense = PackGetInt(p, "NumUserCreationLicense");\r
+       t->ReleaseDate = PackGetInt64(p, "ReleaseDate");\r
+}\r
+void OutRpcLicenseStatus(PACK *p, RPC_LICENSE_STATUS *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "EditionId", t->EditionId);\r
+       PackAddStr(p, "EditionStr", t->EditionStr);\r
+       PackAddInt64(p, "SystemId", t->SystemId);\r
+       PackAddInt64(p, "SystemExpires", t->SystemExpires);\r
+       PackAddInt(p, "NumClientConnectLicense", t->NumClientConnectLicense);\r
+       PackAddInt(p, "NumBridgeConnectLicense", t->NumBridgeConnectLicense);\r
+\r
+       // v3.0\r
+       PackAddBool(p, "NeedSubscription", t->NeedSubscription);\r
+       PackAddBool(p, "AllowEnterpriseFunction", t->AllowEnterpriseFunction);\r
+       PackAddInt64(p, "SubscriptionExpires", t->SubscriptionExpires);\r
+       PackAddBool(p, "IsSubscriptionExpired", t->IsSubscriptionExpired);\r
+       PackAddInt(p, "NumUserCreationLicense", t->NumUserCreationLicense);\r
+       PackAddInt64(p, "ReleaseDate", t->ReleaseDate);\r
+}\r
+\r
+// RPC_ADMIN_OPTION\r
+void InRpcAdminOption(RPC_ADMIN_OPTION *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ADMIN_OPTION));\r
+       t->NumItem = PackGetInt(p, "NumItem");\r
+       t->Items = ZeroMalloc(sizeof(ADMIN_OPTION) * t->NumItem);\r
+\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               ADMIN_OPTION *o = &t->Items[i];\r
+\r
+               PackGetStrEx(p, "Name", o->Name, sizeof(o->Name), i);\r
+               o->Value = PackGetIntEx(p, "Value", i);\r
+       }\r
+}\r
+void OutRpcAdminOption(PACK *p, RPC_ADMIN_OPTION *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "NumItem", t->NumItem);\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+\r
+       for (i = 0;i < t->NumItem;i++)\r
+       {\r
+               ADMIN_OPTION *o = &t->Items[i];\r
+\r
+               PackAddStrEx(p, "Name", o->Name, i, t->NumItem);\r
+               PackAddIntEx(p, "Value", o->Value, i, t->NumItem);\r
+       }\r
+}\r
+void FreeRpcAdminOption(RPC_ADMIN_OPTION *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Items);\r
+}\r
+\r
+// RPC_CONFIG\r
+void InRpcConfig(RPC_CONFIG *t, PACK *p)\r
+{\r
+       UINT size;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_CONFIG));\r
+       PackGetStr(p, "FileName", t->FileName, sizeof(t->FileName));\r
+       size = PackGetDataSize(p, "FileData");\r
+       t->FileData = ZeroMalloc(size + 1);\r
+       PackGetData(p, "FileData", t->FileData);\r
+}\r
+void OutRpcConfig(PACK *p, RPC_CONFIG *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "FileName", t->FileName);\r
+       PackAddData(p, "FileData", t->FileData, StrLen(t->FileData));\r
+}\r
+void FreeRpcConfig(RPC_CONFIG *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->FileData);\r
+}\r
+\r
+// RPC_BRIDGE_SUPPORT\r
+void InRpcBridgeSupport(RPC_BRIDGE_SUPPORT *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_BRIDGE_SUPPORT));\r
+\r
+       t->IsBridgeSupportedOs = PackGetBool(p, "IsBridgeSupportedOs");\r
+       t->IsWinPcapNeeded = PackGetBool(p, "IsWinPcapNeeded");\r
+}\r
+void OutRpcBridgeSupport(PACK *p, RPC_BRIDGE_SUPPORT *t)\r
+{\r
+       // 引数チェック\r
+       if (p == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddBool(p, "IsBridgeSupportedOs", t->IsBridgeSupportedOs);\r
+       PackAddBool(p, "IsWinPcapNeeded",t->IsWinPcapNeeded);\r
+}\r
+\r
+// RPC_ADD_ACCESS\r
+void InRpcAddAccess(RPC_ADD_ACCESS *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ADD_ACCESS));\r
+\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       InRpcAccess(&t->Access, p);\r
+}\r
+void OutRpcAddAccess(PACK *p, RPC_ADD_ACCESS *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       OutRpcAccess(p, &t->Access);\r
+}\r
+\r
+// RPC_DELETE_ACCESS\r
+void InRpcDeleteAccess(RPC_DELETE_ACCESS *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_DELETE_ACCESS));\r
+\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->Id = PackGetInt(p, "Id");\r
+}\r
+void OutRpcDeleteAccess(PACK *p, RPC_DELETE_ACCESS *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddInt(p, "Id", t->Id);\r
+}\r
+\r
+\r
+// RPC_SERVER_INFO\r
+void InRpcServerInfo(RPC_SERVER_INFO *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_SERVER_INFO));\r
+\r
+       PackGetStr(p, "ServerProductName", t->ServerProductName, sizeof(t->ServerProductName));\r
+       PackGetStr(p, "ServerVersionString", t->ServerVersionString, sizeof(t->ServerVersionString));\r
+       PackGetStr(p, "ServerBuildInfoString", t->ServerBuildInfoString, sizeof(t->ServerBuildInfoString));\r
+       t->ServerVerInt = PackGetInt(p, "ServerVerInt");\r
+       t->ServerBuildInt = PackGetInt(p, "ServerBuildInt");\r
+       PackGetStr(p, "ServerHostName", t->ServerHostName, sizeof(t->ServerHostName));\r
+       t->ServerType = PackGetInt(p, "ServerType");\r
+       InRpcOsInfo(&t->OsInfo, p);\r
+}\r
+void OutRpcServerInfo(PACK *p, RPC_SERVER_INFO *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "ServerProductName", t->ServerProductName);\r
+       PackAddStr(p, "ServerVersionString", t->ServerVersionString);\r
+       PackAddStr(p, "ServerBuildInfoString", t->ServerBuildInfoString);\r
+       PackAddInt(p, "ServerVerInt", t->ServerVerInt);\r
+       PackAddInt(p, "ServerBuildInt", t->ServerBuildInt);\r
+       PackAddStr(p, "ServerHostName", t->ServerHostName);\r
+       PackAddInt(p, "ServerType", t->ServerType);\r
+       OutRpcOsInfo(p, &t->OsInfo);\r
+}\r
+void FreeRpcServerInfo(RPC_SERVER_INFO *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       FreeRpcOsInfo(&t->OsInfo);\r
+}\r
+\r
+// RPC_SERVER_STATUS\r
+void InRpcServerStatus(RPC_SERVER_STATUS *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_SERVER_STATUS));\r
+       t->ServerType = PackGetInt(p, "ServerType");\r
+       t->NumTcpConnections = PackGetInt(p, "NumTcpConnections");\r
+       t->NumTcpConnectionsLocal = PackGetInt(p, "NumTcpConnectionsLocal");\r
+       t->NumTcpConnectionsRemote = PackGetInt(p, "NumTcpConnectionsRemote");\r
+       t->NumHubTotal = PackGetInt(p, "NumHubTotal");\r
+       t->NumHubStandalone = PackGetInt(p, "NumHubStandalone");\r
+       t->NumHubStatic = PackGetInt(p, "NumHubStatic");\r
+       t->NumHubDynamic = PackGetInt(p, "NumHubDynamic");\r
+       t->NumSessionsTotal = PackGetInt(p, "NumSessionsTotal");\r
+       t->NumSessionsLocal = PackGetInt(p, "NumSessionsLocal");\r
+       t->NumSessionsRemote = PackGetInt(p, "NumSessionsRemote");\r
+       t->NumMacTables = PackGetInt(p, "NumMacTables");\r
+       t->NumIpTables = PackGetInt(p, "NumIpTables");\r
+       t->NumUsers = PackGetInt(p, "NumUsers");\r
+       t->NumGroups = PackGetInt(p, "NumGroups");\r
+       t->CurrentTime = PackGetInt64(p, "CurrentTime");\r
+       t->CurrentTick = PackGetInt64(p, "CurrentTick");\r
+       t->AssignedBridgeLicenses = PackGetInt(p, "AssignedBridgeLicenses");\r
+       t->AssignedClientLicenses = PackGetInt(p, "AssignedClientLicenses");\r
+       t->AssignedBridgeLicensesTotal = PackGetInt(p, "AssignedBridgeLicensesTotal");\r
+       t->AssignedClientLicensesTotal = PackGetInt(p, "AssignedClientLicensesTotal");\r
+       t->StartTime = PackGetInt64(p, "StartTime");\r
+\r
+       InRpcTraffic(&t->Traffic, p);\r
+\r
+       InRpcMemInfo(&t->MemInfo, p);\r
+}\r
+void OutRpcServerStatus(PACK *p, RPC_SERVER_STATUS *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "ServerType", t->ServerType);\r
+       PackAddInt(p, "NumTcpConnections", t->NumTcpConnections);\r
+       PackAddInt(p, "NumHubTotal", t->NumHubTotal);\r
+       PackAddInt(p, "NumHubStandalone", t->NumHubStandalone);\r
+       PackAddInt(p, "NumHubStatic", t->NumHubStatic);\r
+       PackAddInt(p, "NumHubDynamic", t->NumHubDynamic);\r
+       PackAddInt(p, "NumSessionsTotal", t->NumSessionsTotal);\r
+       PackAddInt(p, "NumSessionsLocal", t->NumSessionsLocal);\r
+       PackAddInt(p, "NumSessionsRemote", t->NumSessionsRemote);\r
+       PackAddInt(p, "NumTcpConnections", t->NumTcpConnections);\r
+       PackAddInt(p, "NumTcpConnectionsLocal", t->NumTcpConnectionsLocal);\r
+       PackAddInt(p, "NumTcpConnectionsRemote", t->NumTcpConnectionsRemote);\r
+       PackAddInt(p, "NumMacTables", t->NumMacTables);\r
+       PackAddInt(p, "NumIpTables", t->NumIpTables);\r
+       PackAddInt(p, "NumUsers", t->NumUsers);\r
+       PackAddInt(p, "NumGroups", t->NumGroups);\r
+       PackAddInt64(p, "CurrentTime", t->CurrentTime);\r
+       PackAddInt64(p, "CurrentTick", t->CurrentTick);\r
+       PackAddInt(p, "AssignedBridgeLicenses", t->AssignedBridgeLicenses);\r
+       PackAddInt(p, "AssignedClientLicenses", t->AssignedClientLicenses);\r
+       PackAddInt(p, "AssignedBridgeLicensesTotal", t->AssignedBridgeLicensesTotal);\r
+       PackAddInt(p, "AssignedClientLicensesTotal", t->AssignedClientLicensesTotal);\r
+       PackAddInt64(p, "StartTime", t->StartTime);\r
+\r
+       OutRpcTraffic(p, &t->Traffic);\r
+\r
+       OutRpcMemInfo(p, &t->MemInfo);\r
+}\r
+\r
+// RPC_LISTENER\r
+void InRpcListener(RPC_LISTENER *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_LISTENER));\r
+       t->Port = PackGetInt(p, "Port");\r
+       t->Enable = PackGetBool(p, "Enable");\r
+}\r
+void OutRpcListener(PACK *p, RPC_LISTENER *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "Port", t->Port);\r
+       PackAddBool(p, "Enable", t->Enable);\r
+}\r
+\r
+// RPC_LISTENER_LIST\r
+void InRpcListenerList(RPC_LISTENER_LIST *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_LISTENER_LIST));\r
+       t->NumPort = PackGetIndexCount(p, "Ports");\r
+       t->Ports = ZeroMalloc(sizeof(UINT) * t->NumPort);\r
+       t->Enables = ZeroMalloc(sizeof(UINT) * t->NumPort);\r
+       t->Errors = ZeroMalloc(sizeof(UINT) * t->NumPort);\r
+       for (i = 0;i < t->NumPort;i++)\r
+       {\r
+               t->Ports[i] = PackGetIntEx(p, "Ports", i);\r
+               t->Enables[i] = PackGetBoolEx(p, "Enables", i);\r
+               t->Errors[i] = PackGetBoolEx(p, "Errors", i);\r
+       }\r
+}\r
+void OutRpcListenerList(PACK *p, RPC_LISTENER_LIST *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 0;i < t->NumPort;i++)\r
+       {\r
+               PackAddIntEx(p, "Ports", t->Ports[i], i, t->NumPort);\r
+               PackAddBoolEx(p, "Enables", t->Enables[i], i, t->NumPort);\r
+               PackAddBoolEx(p, "Errors", t->Errors[i], i, t->NumPort);\r
+       }\r
+}\r
+void FreeRpcListenerList(RPC_LISTENER_LIST *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Ports);\r
+       Free(t->Enables);\r
+       Free(t->Errors);\r
+}\r
+\r
+// RPC_STR\r
+void InRpcStr(RPC_STR *t, PACK *p)\r
+{\r
+       UINT size = 65536;\r
+       char *tmp = Malloc(size);\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_STR));\r
+       if (PackGetStr(p, "String", tmp, size) == false)\r
+       {\r
+               t->String = CopyStr("");\r
+       }\r
+       else\r
+       {\r
+               t->String = CopyStr(tmp);\r
+       }\r
+       Free(tmp);\r
+}\r
+void OutRpcStr(PACK *p, RPC_STR *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "String", t->String);\r
+}\r
+void FreeRpcStr(RPC_STR *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL )\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->String);\r
+}\r
+\r
+// RPC_SET_PASSWORD\r
+void InRpcSetPassword(RPC_SET_PASSWORD *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_SET_PASSWORD));\r
+       PackGetData2(p, "HashedPassword", t->HashedPassword, sizeof(t->HashedPassword));\r
+}\r
+void OutRpcSetPassword(PACK *p, RPC_SET_PASSWORD *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddData(p, "HashedPassword", t->HashedPassword, sizeof(t->HashedPassword));\r
+}\r
+\r
+// RPC_FARM\r
+void InRpcFarm(RPC_FARM *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_FARM));\r
+       t->ServerType = PackGetInt(p, "ServerType");\r
+       t->NumPort = PackGetIndexCount(p, "Ports");\r
+       t->Ports = ZeroMalloc(sizeof(UINT) * t->NumPort);\r
+       for (i = 0;i < t->NumPort;i++)\r
+       {\r
+               t->Ports[i] = PackGetIntEx(p, "Ports", i);\r
+       }\r
+       t->PublicIp = PackGetIp32(p, "PublicIp");\r
+       PackGetStr(p, "ControllerName", t->ControllerName, sizeof(t->ControllerName));\r
+       t->ControllerPort = PackGetInt(p, "ControllerPort");\r
+       PackGetData2(p, "MemberPassword", t->MemberPassword, sizeof(t->MemberPassword));\r
+       t->Weight = PackGetInt(p, "Weight");\r
+       t->ControllerOnly = PackGetBool(p, "ControllerOnly");\r
+}\r
+void OutRpcFarm(PACK *p, RPC_FARM *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "ServerType", t->ServerType);\r
+       for (i = 0;i < t->NumPort;i++)\r
+       {\r
+               PackAddIntEx(p, "Ports", t->Ports[i], i, t->NumPort);\r
+       }\r
+       PackAddIp32(p, "PublicIp", t->PublicIp);\r
+       PackAddStr(p, "ControllerName", t->ControllerName);\r
+       PackAddInt(p, "ControllerPort", t->ControllerPort);\r
+       PackAddData(p, "MemberPassword", t->MemberPassword, sizeof(t->MemberPassword));\r
+       PackAddInt(p, "Weight", t->Weight);\r
+       PackAddBool(p, "ControllerOnly", t->ControllerOnly);\r
+}\r
+void FreeRpcFarm(RPC_FARM *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Ports);\r
+}\r
+\r
+// RPC_FARM_HUB\r
+void InRpcFarmHub(RPC_FARM_HUB *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_FARM_HUB));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->DynamicHub = PackGetBool(p, "DynamicHub");\r
+}\r
+void OutRpcFarmHub(PACK *p, RPC_FARM_HUB *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddBool(p, "DynamicHub", t->DynamicHub);\r
+}\r
+\r
+// RPC_FARM_INFO\r
+void InRpcFarmInfo(RPC_FARM_INFO *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_FARM_INFO));\r
+       t->Id = PackGetInt(p, "Id");\r
+       t->Controller = PackGetBool(p, "Controller");\r
+       t->ConnectedTime = PackGetInt64(p, "ConnectedTime");\r
+       t->Ip = PackGetIp32(p, "Ip");\r
+       PackGetStr(p, "Hostname", t->Hostname, sizeof(t->Hostname));\r
+       t->Point = PackGetInt(p, "Point");\r
+       t->NumPort = PackGetIndexCount(p, "Ports");\r
+       t->Ports = ZeroMalloc(sizeof(UINT) * t->NumPort);\r
+       for (i = 0;i < t->NumPort;i++)\r
+       {\r
+               t->Ports[i] = PackGetIntEx(p, "Ports", i);\r
+       }\r
+       t->ServerCert = PackGetX(p, "ServerCert");\r
+       t->NumFarmHub = PackGetIndexCount(p, "HubName");\r
+       t->FarmHubs = ZeroMalloc(sizeof(RPC_FARM_HUB) * t->NumFarmHub);\r
+       for (i = 0;i < t->NumFarmHub;i++)\r
+       {\r
+               PackGetStrEx(p, "HubName", t->FarmHubs[i].HubName, sizeof(t->FarmHubs[i].HubName), i);\r
+               t->FarmHubs[i].DynamicHub = PackGetBoolEx(p, "DynamicHub", i);\r
+       }\r
+       t->NumSessions = PackGetInt(p, "NumSessions");\r
+       t->NumTcpConnections = PackGetInt(p, "NumTcpConnections");\r
+       t->Weight = PackGetInt(p, "Weight");\r
+}\r
+void OutRpcFarmInfo(PACK *p, RPC_FARM_INFO *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "Id", t->Id);\r
+       PackAddBool(p, "Controller", t->Controller);\r
+       PackAddInt64(p, "ConnectedTime", t->ConnectedTime);\r
+       PackAddIp32(p, "Ip", t->Ip);\r
+       PackAddStr(p, "Hostname", t->Hostname);\r
+       PackAddInt(p, "Point", t->Point);\r
+       for (i = 0;i < t->NumPort;i++)\r
+       {\r
+               PackAddIntEx(p, "Ports", t->Ports[i], i, t->NumPort);\r
+       }\r
+       PackAddX(p, "ServerCert", t->ServerCert);\r
+       for (i = 0;i < t->NumFarmHub;i++)\r
+       {\r
+               PackAddStrEx(p, "HubName", t->FarmHubs[i].HubName, i, t->NumFarmHub);\r
+               PackAddBoolEx(p, "DynamicHub", t->FarmHubs[i].DynamicHub, i, t->NumFarmHub);\r
+       }\r
+       PackAddInt(p, "NumSessions", t->NumSessions);\r
+       PackAddInt(p, "NumTcpConnections", t->NumTcpConnections);\r
+       PackAddInt(p, "Weight", t->Weight);\r
+}\r
+void FreeRpcFarmInfo(RPC_FARM_INFO *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Ports);\r
+       Free(t->FarmHubs);\r
+       FreeX(t->ServerCert);\r
+}\r
+\r
+void InRpcEnumFarm(RPC_ENUM_FARM *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_FARM));\r
+       t->NumFarm = PackGetIndexCount(p, "Id");\r
+       t->Farms = ZeroMalloc(sizeof(RPC_ENUM_FARM_ITEM) * t->NumFarm);\r
+\r
+       for (i = 0;i < t->NumFarm;i++)\r
+       {\r
+               RPC_ENUM_FARM_ITEM *e = &t->Farms[i];\r
+\r
+               e->Id = PackGetIntEx(p, "Id", i);\r
+               e->Controller = PackGetBoolEx(p, "Controller", i);\r
+               e->ConnectedTime = PackGetInt64Ex(p, "ConnectedTime", i);\r
+               e->Ip = PackGetIp32Ex(p, "Ip", i);\r
+               PackGetStrEx(p, "Hostname", e->Hostname, sizeof(e->Hostname), i);\r
+               e->Point = PackGetIntEx(p, "Point", i);\r
+               e->NumSessions = PackGetIntEx(p, "NumSessions", i);\r
+               e->NumTcpConnections = PackGetIntEx(p, "NumTcpConnections", i);\r
+               e->NumHubs = PackGetIntEx(p, "NumHubs", i);\r
+               e->AssignedClientLicense = PackGetIntEx(p, "AssignedClientLicense", i);\r
+               e->AssignedBridgeLicense = PackGetIntEx(p, "AssignedBridgeLicense", i);\r
+       }\r
+}\r
+void OutRpcEnumFarm(PACK *p, RPC_ENUM_FARM *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 0;i < t->NumFarm;i++)\r
+       {\r
+               RPC_ENUM_FARM_ITEM *e = &t->Farms[i];\r
+\r
+               PackAddIntEx(p, "Id", e->Id, i, t->NumFarm);\r
+               PackAddBoolEx(p, "Controller", e->Controller, i, t->NumFarm);\r
+               PackAddInt64Ex(p, "ConnectedTime", e->ConnectedTime, i, t->NumFarm);\r
+               PackAddIp32Ex(p, "Ip", e->Ip, i, t->NumFarm);\r
+               PackAddStrEx(p, "Hostname", e->Hostname, i, t->NumFarm);\r
+               PackAddIntEx(p, "Point", e->Point, i, t->NumFarm);\r
+               PackAddIntEx(p, "NumSessions", e->NumSessions, i, t->NumFarm);\r
+               PackAddIntEx(p, "NumTcpConnections", e->NumTcpConnections, i, t->NumFarm);\r
+               PackAddIntEx(p, "NumHubs", e->NumHubs, i, t->NumFarm);\r
+               PackAddIntEx(p, "AssignedClientLicense", e->AssignedClientLicense, i, t->NumFarm);\r
+               PackAddIntEx(p, "AssignedBridgeLicense", e->AssignedBridgeLicense, i, t->NumFarm);\r
+       }\r
+}\r
+void FreeRpcEnumFarm(RPC_ENUM_FARM *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Farms);\r
+}\r
+\r
+// RPC_FARM_CONNECTION_STATUS\r
+void InRpcFarmConnectionStatus(RPC_FARM_CONNECTION_STATUS *t, PACK *p)\r
+{\r
+       Zero(t, sizeof(RPC_FARM_CONNECTION_STATUS));\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       t->Ip = PackGetIp32(p, "Ip");\r
+       t->Port = PackGetInt(p, "Port");\r
+       t->Online = PackGetBool(p, "Online");\r
+       t->LastError = PackGetInt(p, "LastError");\r
+       t->StartedTime = PackGetInt64(p, "StartedTime");\r
+       t->CurrentConnectedTime = PackGetInt64(p, "CurrentConnectedTime");\r
+       t->FirstConnectedTime = PackGetInt64(p, "FirstConnectedTime");\r
+       t->NumConnected = PackGetInt(p, "NumConnected");\r
+       t->NumTry = PackGetInt(p, "NumTry");\r
+       t->NumFailed = PackGetInt(p, "NumFailed");\r
+}\r
+void OutRpcFarmConnectionStatus(PACK *p, RPC_FARM_CONNECTION_STATUS *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddIp32(p, "Ip", t->Ip);\r
+       PackAddInt(p, "Port", t->Port);\r
+       PackAddBool(p, "Online", t->Online);\r
+       PackAddInt(p, "LastError", t->LastError);\r
+       PackAddInt64(p, "StartedTime", t->StartedTime);\r
+       PackAddInt64(p, "CurrentConnectedTime", t->CurrentConnectedTime);\r
+       PackAddInt64(p, "FirstConnectedTime", t->FirstConnectedTime);\r
+       PackAddInt(p, "NumConnected", t->NumConnected);\r
+       PackAddInt(p, "NumTry", t->NumTry);\r
+       PackAddInt(p, "NumFailed", t->NumFailed);\r
+}\r
+\r
+// RPC_HUB_OPTION\r
+void InRpcHubOption(RPC_HUB_OPTION *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_HUB_OPTION));\r
+       t->MaxSession = PackGetInt(p, "MaxSession");\r
+       t->NoEnum = PackGetBool(p, "NoEnum");\r
+}\r
+void OutRpcHubOption(PACK *p, RPC_HUB_OPTION *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "MaxSession", t->MaxSession);\r
+       PackAddBool(p, "NoEnum", t->NoEnum);\r
+}\r
+\r
+// RPC_RADIUS\r
+void InRpcRadius(RPC_RADIUS *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_RADIUS));\r
+       PackGetStr(p, "RadiusServerName", t->RadiusServerName, sizeof(t->RadiusServerName));\r
+       t->RadiusPort = PackGetInt(p, "RadiusPort");\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       PackGetStr(p, "RadiusSecret", t->RadiusSecret, sizeof(t->RadiusSecret));\r
+       t->RadiusRetryInterval = PackGetInt(p, "RadiusRetryInterval");\r
+}\r
+void OutRpcRadius(PACK *p, RPC_RADIUS *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "RadiusServerName", t->RadiusServerName);\r
+       PackAddInt(p, "RadiusPort", t->RadiusPort);\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddStr(p, "RadiusSecret", t->RadiusSecret);\r
+       PackAddInt(p, "RadiusRetryInterval", t->RadiusRetryInterval);\r
+}\r
+\r
+// RPC_HUB\r
+void InRpcHub(RPC_HUB *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_HUB));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+}\r
+void OutRpcHub(PACK *p, RPC_HUB *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+}\r
+\r
+// RPC_CREATE_HUB\r
+void InRpcCreateHub(RPC_CREATE_HUB *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_CREATE_HUB));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       PackGetData2(p, "HashedPassword", t->HashedPassword, sizeof(t->HashedPassword));\r
+       PackGetData2(p, "SecurePassword", t->SecurePassword, sizeof(t->SecurePassword));\r
+       t->Online = PackGetBool(p, "Online");\r
+       InRpcHubOption(&t->HubOption, p);\r
+       t->HubType = PackGetInt(p, "HubType");\r
+}\r
+void OutRpcCreateHub(PACK *p, RPC_CREATE_HUB *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddData(p, "HashedPassword", t->HashedPassword, sizeof(t->HashedPassword));\r
+       PackAddData(p, "SecurePassword", t->SecurePassword, sizeof(t->SecurePassword));\r
+       PackAddBool(p, "Online", t->Online);\r
+       OutRpcHubOption(p, &t->HubOption);\r
+       PackAddInt(p, "HubType", t->HubType);\r
+}\r
+\r
+// RPC_ENUM_HUB\r
+void InRpcEnumHub(RPC_ENUM_HUB *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_HUB));\r
+       t->NumHub = PackGetIndexCount(p, "HubName");\r
+       t->Hubs = ZeroMalloc(sizeof(RPC_ENUM_HUB_ITEM) * t->NumHub);\r
+\r
+       for (i = 0;i < t->NumHub;i++)\r
+       {\r
+               RPC_ENUM_HUB_ITEM *e = &t->Hubs[i];\r
+\r
+               PackGetStrEx(p, "HubName", e->HubName, sizeof(e->HubName), i);\r
+               e->Online = PackGetBoolEx(p, "Online", i);\r
+               e->HubType = PackGetIntEx(p, "HubType", i);\r
+               e->NumSessions = PackGetIntEx(p, "NumSessions", i);\r
+               e->NumUsers = PackGetIntEx(p, "NumUsers", i);\r
+               e->NumGroups = PackGetIntEx(p, "NumGroups", i);\r
+               e->NumMacTables = PackGetIntEx(p, "NumMacTables", i);\r
+               e->NumIpTables = PackGetIntEx(p, "NumIpTables", i);\r
+               e->LastCommTime = PackGetInt64Ex(p, "LastCommTime", i);\r
+               e->CreatedTime = PackGetInt64Ex(p, "CreatedTime", i);\r
+               e->LastLoginTime = PackGetInt64Ex(p, "LastLoginTime", i);\r
+               e->NumLogin = PackGetIntEx(p, "NumLogin", i);\r
+       }\r
+}\r
+void OutRpcEnumHub(PACK *p, RPC_ENUM_HUB *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 0;i < t->NumHub;i++)\r
+       {\r
+               RPC_ENUM_HUB_ITEM *e = &t->Hubs[i];\r
+\r
+               PackAddStrEx(p, "HubName", e->HubName, i, t->NumHub);\r
+               PackAddBoolEx(p, "Online", e->Online, i, t->NumHub);\r
+               PackAddIntEx(p, "HubType", e->HubType, i, t->NumHub);\r
+               PackAddIntEx(p, "NumSessions", e->NumSessions, i, t->NumHub);\r
+               PackAddIntEx(p, "NumUsers", e->NumUsers, i, t->NumHub);\r
+               PackAddIntEx(p, "NumGroups", e->NumGroups, i, t->NumHub);\r
+               PackAddIntEx(p, "NumMacTables", e->NumMacTables, i, t->NumHub);\r
+               PackAddIntEx(p, "NumIpTables", e->NumIpTables, i, t->NumHub);\r
+               PackAddInt64Ex(p, "LastCommTime", e->LastCommTime, i, t->NumHub);\r
+               PackAddInt64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumHub);\r
+               PackAddInt64Ex(p, "LastLoginTime", e->LastLoginTime, i, t->NumHub);\r
+               PackAddIntEx(p, "NumLogin", e->NumLogin, i, t->NumHub);\r
+       }\r
+}\r
+void FreeRpcEnumHub(RPC_ENUM_HUB *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Hubs);\r
+}\r
+\r
+// RPC_DELETE_HUB\r
+void InRpcDeleteHub(RPC_DELETE_HUB *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_DELETE_HUB));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+}\r
+void OutRpcDeleteHub(PACK *p, RPC_DELETE_HUB *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+}\r
+\r
+// RPC_ENUM_CONNECTION\r
+void InRpcEnumConnection(RPC_ENUM_CONNECTION *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_CONNECTION));\r
+       t->NumConnection = PackGetIndexCount(p, "Name");\r
+       t->Connections = ZeroMalloc(sizeof(RPC_ENUM_CONNECTION_ITEM) * t->NumConnection);\r
+\r
+       for (i = 0;i < t->NumConnection;i++)\r
+       {\r
+               RPC_ENUM_CONNECTION_ITEM *e = &t->Connections[i];\r
+\r
+               e->Ip = PackGetIp32Ex(p, "Ip", i);\r
+               e->Port = PackGetIntEx(p, "Port", i);\r
+               PackGetStrEx(p, "Name", e->Name, sizeof(e->Name), i);\r
+               PackGetStrEx(p, "Hostname", e->Hostname, sizeof(e->Hostname), i);\r
+               e->ConnectedTime = PackGetInt64Ex(p, "ConnectedTime", i);\r
+               e->Type = PackGetIntEx(p, "Type", i);\r
+       }\r
+}\r
+void OutRpcEnumConnection(PACK *p, RPC_ENUM_CONNECTION *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 0;i < t->NumConnection;i++)\r
+       {\r
+               RPC_ENUM_CONNECTION_ITEM *e = &t->Connections[i];\r
+\r
+               PackAddIp32Ex(p, "Ip", e->Ip, i, t->NumConnection);\r
+               PackAddIntEx(p, "Port", e->Port, i, t->NumConnection);\r
+               PackAddStrEx(p, "Name", e->Name, i, t->NumConnection);\r
+               PackAddStrEx(p, "Hostname", e->Hostname, i, t->NumConnection);\r
+               PackAddInt64Ex(p, "ConnectedTime", e->ConnectedTime, i, t->NumConnection);\r
+               PackAddIntEx(p, "Type", e->Type, i, t->NumConnection);\r
+       }\r
+}\r
+void FreeRpcEnumConnetion(RPC_ENUM_CONNECTION *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Connections);\r
+}\r
+\r
+// RPC_DISCONNECT_CONNECTION\r
+void InRpcDisconnectConnection(RPC_DISCONNECT_CONNECTION *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_DISCONNECT_CONNECTION));\r
+       PackGetStr(p, "Name", t->Name, sizeof(t->Name));\r
+}\r
+void OutRpcDisconnectConnection(PACK *p, RPC_DISCONNECT_CONNECTION *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "Name", t->Name);\r
+}\r
+\r
+// RPC_CONNECTION_INFO\r
+void InRpcConnectionInfo(RPC_CONNECTION_INFO *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_CONNECTION_INFO));\r
+       PackGetStr(p, "Name", t->Name, sizeof(t->Name));\r
+       t->Ip = PackGetIp32(p, "Ip");\r
+       t->Port = PackGetInt(p, "Port");\r
+       t->ConnectedTime = PackGetInt64(p, "ConnectedTime");\r
+       PackGetStr(p, "Hostname", t->Hostname, sizeof(t->Hostname));\r
+       PackGetStr(p, "ServerStr", t->ServerStr, sizeof(t->ServerStr));\r
+       PackGetStr(p, "ClientStr", t->ClientStr, sizeof(t->ClientStr));\r
+       t->ServerVer = PackGetInt(p, "ServerVer");\r
+       t->ServerBuild = PackGetInt(p, "ServerBuild");\r
+       t->ClientVer = PackGetInt(p, "ClientVer");\r
+       t->ClientBuild = PackGetInt(p, "ClientBuild");\r
+       t->Type = PackGetInt(p, "Type");\r
+}\r
+void OutRpcConnectionInfo(PACK *p, RPC_CONNECTION_INFO *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "Name", t->Name);\r
+       PackAddIp32(p, "Ip", t->Ip);\r
+       PackAddInt(p, "Port", t->Port);\r
+       PackAddInt64(p, "ConnectedTime", t->ConnectedTime);\r
+       PackAddStr(p, "Hostname", t->Hostname);\r
+       PackAddStr(p, "ServerStr", t->ServerStr);\r
+       PackAddStr(p, "ClientStr", t->ClientStr);\r
+       PackAddInt(p, "ServerVer", t->ServerVer);\r
+       PackAddInt(p, "ServerBuild", t->ServerBuild);\r
+       PackAddInt(p, "ClientVer", t->ClientVer);\r
+       PackAddInt(p, "ClientBuild", t->ClientBuild);\r
+       PackAddInt(p, "Type", t->Type);\r
+}\r
+\r
+// RPC_SET_HUB_ONLINE\r
+void InRpcSetHubOnline(RPC_SET_HUB_ONLINE *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_SET_HUB_ONLINE));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->Online = PackGetBool(p, "Online");\r
+}\r
+void OutRpcSetHubOnline(PACK *p, RPC_SET_HUB_ONLINE *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddBool(p, "Online", t->Online);\r
+}\r
+\r
+// RPC_HUB_STATUS\r
+void InRpcHubStatus(RPC_HUB_STATUS *t, PACK *p)\r
+{\r
+       Zero(t, sizeof(RPC_HUB_STATUS));\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->Online = PackGetBool(p, "Online");\r
+       t->HubType = PackGetInt(p, "HubType");\r
+       t->NumSessions = PackGetInt(p, "NumSessions");\r
+       t->NumSessionsClient = PackGetInt(p, "NumSessionsClient");\r
+       t->NumSessionsBridge = PackGetInt(p, "NumSessionsBridge");\r
+       t->NumAccessLists = PackGetInt(p, "NumAccessLists");\r
+       t->NumUsers = PackGetInt(p, "NumUsers");\r
+       t->NumGroups = PackGetInt(p, "NumGroups");\r
+       t->NumMacTables = PackGetInt(p, "NumMacTables");\r
+       t->NumIpTables = PackGetInt(p, "NumIpTables");\r
+       t->SecureNATEnabled = PackGetBool(p, "SecureNATEnabled");\r
+       InRpcTraffic(&t->Traffic, p);\r
+       t->LastCommTime = PackGetInt64(p, "LastCommTime");\r
+       t->CreatedTime = PackGetInt64(p, "CreatedTime");\r
+       t->LastLoginTime = PackGetInt64(p, "LastLoginTime");\r
+       t->NumLogin = PackGetInt(p, "NumLogin");\r
+}\r
+void OutRpcHubStatus(PACK *p, RPC_HUB_STATUS *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddBool(p, "Online", t->Online);\r
+       PackAddInt(p, "HubType", t->HubType);\r
+       PackAddInt(p, "NumSessions", t->NumSessions);\r
+       PackAddInt(p, "NumSessionsClient", t->NumSessionsClient);\r
+       PackAddInt(p, "NumSessionsBridge", t->NumSessionsBridge);\r
+       PackAddInt(p, "NumAccessLists", t->NumAccessLists);\r
+       PackAddInt(p, "NumUsers", t->NumUsers);\r
+       PackAddInt(p, "NumGroups", t->NumGroups);\r
+       PackAddInt(p, "NumMacTables", t->NumMacTables);\r
+       PackAddInt(p, "NumIpTables", t->NumIpTables);\r
+       PackAddBool(p, "SecureNATEnabled", t->SecureNATEnabled);\r
+       OutRpcTraffic(p, &t->Traffic);\r
+       PackAddInt64(p, "LastCommTime", t->LastCommTime);\r
+       PackAddInt64(p, "CreatedTime", t->CreatedTime);\r
+       PackAddInt64(p, "LastLoginTime", t->LastLoginTime);\r
+       PackAddInt(p, "NumLogin", t->NumLogin);\r
+}\r
+\r
+// RPC_HUB_LOG\r
+void InRpcHubLog(RPC_HUB_LOG *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_HUB_LOG));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->LogSetting.SaveSecurityLog = PackGetBool(p, "SaveSecurityLog");\r
+       t->LogSetting.SecurityLogSwitchType = PackGetInt(p, "SecurityLogSwitchType");\r
+       t->LogSetting.SavePacketLog = PackGetBool(p, "SavePacketLog");\r
+       t->LogSetting.PacketLogSwitchType = PackGetInt(p, "PacketLogSwitchType");\r
+       for (i = 0;i < NUM_PACKET_LOG;i++)\r
+       {\r
+               t->LogSetting.PacketLogConfig[i] = PackGetIntEx(p, "PacketLogConfig", i);\r
+       }\r
+}\r
+void OutRpcHubLog(PACK *p, RPC_HUB_LOG *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddBool(p, "SaveSecurityLog", t->LogSetting.SaveSecurityLog);\r
+       PackAddInt(p, "SecurityLogSwitchType", t->LogSetting.SecurityLogSwitchType);\r
+       PackAddBool(p, "SavePacketLog", t->LogSetting.SavePacketLog);\r
+       PackAddInt(p, "PacketLogSwitchType", t->LogSetting.PacketLogSwitchType);\r
+       for (i = 0;i < NUM_PACKET_LOG;i++)\r
+       {\r
+               PackAddIntEx(p, "PacketLogConfig", t->LogSetting.PacketLogConfig[i], i, NUM_PACKET_LOG);\r
+       }\r
+}\r
+\r
+// RPC_HUB_ADD_CA\r
+void InRpcHubAddCa(RPC_HUB_ADD_CA *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_HUB_ADD_CA));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->Cert = PackGetX(p, "Cert");\r
+}\r
+void OutRpcHubAddCa(PACK *p, RPC_HUB_ADD_CA *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddX(p, "Cert", t->Cert);\r
+}\r
+void FreeRpcHubAddCa(RPC_HUB_ADD_CA *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       FreeX(t->Cert);\r
+}\r
+\r
+// RPC_HUB_ENUM_CA\r
+void InRpcHubEnumCa(RPC_HUB_ENUM_CA *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_HUB_ENUM_CA));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->NumCa = PackGetIndexCount(p, "Key");\r
+       t->Ca = ZeroMalloc(sizeof(RPC_HUB_ENUM_CA_ITEM) * t->NumCa);\r
+\r
+       for (i = 0;i < t->NumCa;i++)\r
+       {\r
+               RPC_HUB_ENUM_CA_ITEM *e = &t->Ca[i];\r
+\r
+               e->Key = PackGetIntEx(p, "Key", i);\r
+               PackGetUniStrEx(p, "SubjectName", e->SubjectName, sizeof(e->SubjectName), i);\r
+               PackGetUniStrEx(p, "IssuerName", e->IssuerName, sizeof(e->IssuerName), i);\r
+               e->Expires = PackGetInt64Ex(p, "Expires", i);\r
+       }\r
+}\r
+void OutRpcHubEnumCa(PACK *p, RPC_HUB_ENUM_CA *t)\r
+{\r
+       UINT i;\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 0;i < t->NumCa;i++)\r
+       {\r
+               RPC_HUB_ENUM_CA_ITEM *e = &t->Ca[i];\r
+\r
+               PackAddIntEx(p, "Key", e->Key, i, t->NumCa);\r
+               PackAddUniStrEx(p, "SubjectName", e->SubjectName, i, t->NumCa);\r
+               PackAddUniStrEx(p, "IssuerName", e->IssuerName, i, t->NumCa);\r
+               PackAddInt64Ex(p, "Expires", e->Expires, i, t->NumCa);\r
+       }\r
+}\r
+void FreeRpcHubEnumCa(RPC_HUB_ENUM_CA *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Ca);\r
+}\r
+\r
+// RPC_HUB_GET_CA\r
+void InRpcHubGetCa(RPC_HUB_GET_CA *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_HUB_GET_CA));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->Key = PackGetInt(p, "Key");\r
+       t->Cert = PackGetX(p, "Cert");\r
+}\r
+void OutRpcHubGetCa(PACK *p, RPC_HUB_GET_CA *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddInt(p, "Key", t->Key);\r
+       PackAddX(p, "Cert", t->Cert);\r
+}\r
+void FreeRpcHubGetCa(RPC_HUB_GET_CA *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       FreeX(t->Cert);\r
+}\r
+\r
+// RPC_HUB_DELETE_CA\r
+void InRpcHubDeleteCa(RPC_HUB_DELETE_CA *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_HUB_DELETE_CA));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->Key = PackGetInt(p, "Key");\r
+}\r
+void OutRpcHubDeleteCa(PACK *p, RPC_HUB_DELETE_CA *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddInt(p, "Key", t->Key);\r
+}\r
+\r
+// RPC_CREATE_LINK\r
+void InRpcCreateLink(RPC_CREATE_LINK *t, PACK *p)\r
+{\r
+       BUF *b;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_CREATE_LINK));\r
+       PackGetStr(p, "HubName_Ex", t->HubName, sizeof(t->HubName));\r
+       t->Online = PackGetBool(p, "Online");\r
+       t->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       InRpcClientOption(t->ClientOption, p);\r
+       t->ClientAuth  = ZeroMalloc(sizeof(CLIENT_AUTH));\r
+       InRpcClientAuth(t->ClientAuth, p);\r
+       InRpcPolicy(&t->Policy, p);\r
+\r
+       t->CheckServerCert = PackGetBool(p, "CheckServerCert");\r
+       b = PackGetBuf(p, "ServerCert");\r
+       if (b != NULL)\r
+       {\r
+               t->ServerCert = BufToX(b, false);\r
+               FreeBuf(b);\r
+       }\r
+}\r
+void OutRpcCreateLink(PACK *p, RPC_CREATE_LINK *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName_Ex",t->HubName);\r
+       PackAddBool(p, "Online", t->Online);\r
+       OutRpcClientOption(p, t->ClientOption);\r
+       OutRpcClientAuth(p, t->ClientAuth);\r
+       OutRpcPolicy(p, &t->Policy);\r
+\r
+       PackAddBool(p, "CheckServerCert", t->CheckServerCert);\r
+       if (t->ServerCert != NULL)\r
+       {\r
+               BUF *b;\r
+               b = XToBuf(t->ServerCert, false);\r
+               PackAddBuf(p, "ServerCert", b);\r
+               FreeBuf(b);\r
+       }\r
+}\r
+void FreeRpcCreateLink(RPC_CREATE_LINK *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (t->ServerCert != NULL)\r
+       {\r
+               FreeX(t->ServerCert);\r
+       }\r
+       Free(t->ClientOption);\r
+       CiFreeClientAuth(t->ClientAuth);\r
+}\r
+\r
+// RPC_ENUM_LINK\r
+void InRpcEnumLink(RPC_ENUM_LINK *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_LINK));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->NumLink = PackGetIndexCount(p, "AccountName");\r
+       t->Links = ZeroMalloc(sizeof(RPC_ENUM_LINK_ITEM) * t->NumLink);\r
+\r
+       for (i = 0;i < t->NumLink;i++)\r
+       {\r
+               RPC_ENUM_LINK_ITEM *e = &t->Links[i];\r
+\r
+               PackGetUniStrEx(p, "AccountName", e->AccountName, sizeof(e->AccountName), i);\r
+               PackGetStrEx(p, "Hostname", e->Hostname, sizeof(e->Hostname), i);\r
+               PackGetStrEx(p, "ConnectedHubName", e->HubName, sizeof(e->HubName), i);\r
+               e->Online = PackGetBoolEx(p, "Online", i);\r
+               e->ConnectedTime = PackGetInt64Ex(p, "ConnectedTime", i);\r
+               e->Connected = PackGetBoolEx(p, "Connected", i);\r
+               e->LastError = PackGetIntEx(p, "LastError", i);\r
+       }\r
+}\r
+void OutRpcEnumLink(PACK *p, RPC_ENUM_LINK *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+\r
+       for (i = 0;i < t->NumLink;i++)\r
+       {\r
+               RPC_ENUM_LINK_ITEM *e = &t->Links[i];\r
+\r
+               PackAddUniStrEx(p, "AccountName", e->AccountName, i, t->NumLink);\r
+               PackAddStrEx(p, "ConnectedHubName", e->HubName, i, t->NumLink);\r
+               PackAddStrEx(p, "Hostname", e->Hostname, i, t->NumLink);\r
+               PackAddBoolEx(p, "Online", e->Online, i, t->NumLink);\r
+               PackAddInt64Ex(p, "ConnectedTime", e->ConnectedTime, i, t->NumLink);\r
+               PackAddBoolEx(p, "Connected", e->Connected, i, t->NumLink);\r
+               PackAddIntEx(p, "LastError", e->LastError, i, t->NumLink);\r
+       }\r
+}\r
+void FreeRpcEnumLink(RPC_ENUM_LINK *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Links);\r
+}\r
+\r
+// RPC_LINK_STATUS\r
+void InRpcLinkStatus(RPC_LINK_STATUS *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_LINK_STATUS));\r
+       PackGetStr(p, "HubName_Ex", t->HubName, sizeof(t->HubName));\r
+       PackGetUniStr(p, "AccountName", t->AccountName, sizeof(t->AccountName));\r
+       InRpcClientGetConnectionStatus(&t->Status, p);\r
+}\r
+void OutRpcLinkStatus(PACK *p, RPC_LINK_STATUS *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName_Ex", t->HubName);\r
+       PackAddUniStr(p, "AccountName", t->AccountName);\r
+       OutRpcClientGetConnectionStatus(p, &t->Status);\r
+}\r
+void FreeRpcLinkStatus(RPC_LINK_STATUS *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       CiFreeClientGetConnectionStatus(&t->Status);\r
+}\r
+\r
+// RPC_LINK\r
+void InRpcLink(RPC_LINK *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_LINK));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       PackGetUniStr(p, "AccountName", t->AccountName, sizeof(t->AccountName));\r
+}\r
+void OutRpcLink(PACK *p, RPC_LINK *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddUniStr(p, "AccountName", t->AccountName);\r
+}\r
+\r
+// RPC_RENAME_LINK\r
+void InRpcRenameLink(RPC_RENAME_LINK *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_RENAME_LINK));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       PackGetUniStr(p, "OldAccountName", t->OldAccountName, sizeof(t->OldAccountName));\r
+       PackGetUniStr(p, "NewAccountName", t->NewAccountName, sizeof(t->NewAccountName));\r
+}\r
+void OutRpcRenameLink(PACK *p, RPC_RENAME_LINK *t)\r
+{\r
+       // 引数チェック\r
+       if (p == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddUniStr(p, "OldAccountName", t->OldAccountName);\r
+       PackAddUniStr(p, "NewAccountName", t->NewAccountName);\r
+}\r
+\r
+// ACCESS\r
+void InRpcAccessEx(ACCESS *a, PACK *p, UINT index)\r
+{\r
+       // 引数チェック\r
+       if (a == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(a, sizeof(ACCESS));\r
+       a->Id = PackGetIntEx(p, "Id", index);\r
+       PackGetUniStrEx(p, "Note", a->Note, sizeof(a->Note), index);\r
+       a->Active = PackGetBoolEx(p, "Active", index);\r
+       a->Priority = PackGetIntEx(p, "Priority", index);\r
+       a->Discard = PackGetBoolEx(p, "Discard", index);\r
+       a->SrcIpAddress = PackGetIp32Ex(p, "SrcIpAddress", index);\r
+       a->SrcSubnetMask = PackGetIp32Ex(p, "SrcSubnetMask", index);\r
+       a->DestIpAddress = PackGetIp32Ex(p, "DestIpAddress", index);\r
+       a->DestSubnetMask = PackGetIp32Ex(p, "DestSubnetMask", index);\r
+       a->Protocol = PackGetIntEx(p, "Protocol", index);\r
+       a->SrcPortStart = PackGetIntEx(p, "SrcPortStart", index);\r
+       a->SrcPortEnd = PackGetIntEx(p, "SrcPortEnd", index);\r
+       a->DestPortStart = PackGetIntEx(p, "DestPortStart", index);\r
+       a->DestPortEnd = PackGetIntEx(p, "DestPortEnd", index);\r
+       a->SrcUsernameHash = PackGetIntEx(p, "SrcUsernameHash", index);\r
+       PackGetStrEx(p, "SrcUsername", a->SrcUsername, sizeof(a->SrcUsername), index);\r
+       a->DestUsernameHash = PackGetIntEx(p, "DestUsernameHash", index);\r
+       PackGetStrEx(p, "DestUsername", a->DestUsername, sizeof(a->DestUsername), index);\r
+       a->CheckSrcMac = PackGetBoolEx(p, "CheckSrcMac", index);\r
+       PackGetDataEx2(p, "SrcMacAddress", a->SrcMacAddress, sizeof(a->SrcMacAddress), index);\r
+       PackGetDataEx2(p, "SrcMacMask", a->SrcMacMask, sizeof(a->SrcMacMask), index);\r
+       a->CheckDstMac = PackGetBoolEx(p, "CheckDstMac", index);\r
+       PackGetDataEx2(p, "DstMacAddress", a->DstMacAddress, sizeof(a->DstMacAddress), index);\r
+       PackGetDataEx2(p, "DstMacMask", a->DstMacMask, sizeof(a->DstMacMask), index);\r
+       a->CheckTcpState = PackGetBoolEx(p, "CheckTcpState", index);\r
+       a->Established = PackGetBoolEx(p, "Established", index);\r
+       a->Delay = PackGetIntEx(p, "Delay", index);\r
+       a->Jitter = PackGetIntEx(p, "Jitter", index);\r
+       a->Loss = PackGetIntEx(p, "Loss", index);\r
+       a->IsIPv6 = PackGetBoolEx(p, "IsIPv6", index);\r
+       if (a->IsIPv6)\r
+       {\r
+               PackGetIp6AddrEx(p, "SrcIpAddress6", &a->SrcIpAddress6, index);\r
+               PackGetIp6AddrEx(p, "SrcSubnetMask6", &a->SrcSubnetMask6, index);\r
+               PackGetIp6AddrEx(p, "DestIpAddress6", &a->DestIpAddress6, index);\r
+               PackGetIp6AddrEx(p, "DestSubnetMask6", &a->DestSubnetMask6, index);\r
+       }\r
+}\r
+void InRpcAccess(ACCESS *a, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (a == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       InRpcAccessEx(a, p, 0);\r
+}\r
+void OutRpcAccessEx(PACK *p, ACCESS *a, UINT index, UINT total)\r
+{\r
+       // 引数チェック\r
+       if (a == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddIntEx(p, "Id", a->Id, index, total);\r
+       PackAddUniStrEx(p, "Note", a->Note, index, total);\r
+       PackAddBoolEx(p, "Active", a->Active, index, total);\r
+       PackAddIntEx(p, "Priority", a->Priority, index, total);\r
+       PackAddBoolEx(p, "Discard", a->Discard, index, total);\r
+       if (a->IsIPv6)\r
+       {\r
+               PackAddIp32Ex(p, "SrcIpAddress", 0xFDFFFFDF, index, total);\r
+               PackAddIp32Ex(p, "SrcSubnetMask", 0xFFFFFFFF, index, total);\r
+               PackAddIp32Ex(p, "DestIpAddress", 0xFDFFFFDF, index, total);\r
+               PackAddIp32Ex(p, "DestSubnetMask", 0xFFFFFFFF, index, total);\r
+       }\r
+       else\r
+       {\r
+               PackAddIp32Ex(p, "SrcIpAddress", a->SrcIpAddress, index, total);\r
+               PackAddIp32Ex(p, "SrcSubnetMask", a->SrcSubnetMask, index, total);\r
+               PackAddIp32Ex(p, "DestIpAddress", a->DestIpAddress, index, total);\r
+               PackAddIp32Ex(p, "DestSubnetMask", a->DestSubnetMask, index, total);\r
+       }\r
+       PackAddIntEx(p, "Protocol", a->Protocol, index, total);\r
+       PackAddIntEx(p, "SrcPortStart", a->SrcPortStart, index, total);\r
+       PackAddIntEx(p, "SrcPortEnd", a->SrcPortEnd, index, total);\r
+       PackAddIntEx(p, "DestPortStart", a->DestPortStart, index, total);\r
+       PackAddIntEx(p, "DestPortEnd", a->DestPortEnd, index, total);\r
+       PackAddIntEx(p, "SrcUsernameHash", a->SrcUsernameHash, index, total);\r
+       PackAddStrEx(p, "SrcUsername", a->SrcUsername, index, total);\r
+       PackAddIntEx(p, "DestUsernameHash", a->DestUsernameHash, index, total);\r
+       PackAddStrEx(p, "DestUsername", a->DestUsername, index, total);\r
+       PackAddBoolEx(p, "CheckSrcMac", a->CheckSrcMac, index, total);\r
+       PackAddDataEx(p, "SrcMacAddress", a->SrcMacAddress, sizeof(a->SrcMacAddress), index, total);\r
+       PackAddDataEx(p, "SrcMacMask", a->SrcMacMask, sizeof(a->SrcMacMask), index, total);\r
+       PackAddBoolEx(p, "CheckDstMac", a->CheckDstMac, index, total);\r
+       PackAddDataEx(p, "DstMacAddress", a->DstMacAddress, sizeof(a->DstMacAddress), index, total);\r
+       PackAddDataEx(p, "DstMacMask", a->DstMacMask, sizeof(a->DstMacMask), index, total);\r
+       PackAddBoolEx(p, "CheckTcpState", a->CheckTcpState, index, total);\r
+       PackAddBoolEx(p, "Established", a->Established, index, total);\r
+       PackAddIntEx(p, "Delay", a->Delay, index, total);\r
+       PackAddIntEx(p, "Jitter", a->Jitter, index, total);\r
+       PackAddIntEx(p, "Loss", a->Loss, index, total);\r
+       PackAddBoolEx(p, "IsIPv6", a->IsIPv6, index, total);\r
+       if (a->IsIPv6)\r
+       {\r
+               PackAddIp6AddrEx(p, "SrcIpAddress6", &a->SrcIpAddress6, index, total);\r
+               PackAddIp6AddrEx(p, "SrcSubnetMask6", &a->SrcSubnetMask6, index, total);\r
+               PackAddIp6AddrEx(p, "DestIpAddress6", &a->DestIpAddress6, index, total);\r
+               PackAddIp6AddrEx(p, "DestSubnetMask6", &a->DestSubnetMask6, index, total);\r
+       }\r
+       else\r
+       {\r
+               IPV6_ADDR zero;\r
+\r
+               Zero(&zero, sizeof(zero));\r
+\r
+               PackAddIp6AddrEx(p, "SrcIpAddress6", &zero, index, total);\r
+               PackAddIp6AddrEx(p, "SrcSubnetMask6", &zero, index, total);\r
+               PackAddIp6AddrEx(p, "DestIpAddress6", &zero, index, total);\r
+               PackAddIp6AddrEx(p, "DestSubnetMask6", &zero, index, total);\r
+       }\r
+}\r
+void OutRpcAccess(PACK *p, ACCESS *a)\r
+{\r
+       // 引数チェック\r
+       if (a == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       OutRpcAccessEx(p, a, 0, 1);\r
+}\r
+\r
+// RPC_ENUM_ACCESS_LIST\r
+void InRpcEnumAccessList(RPC_ENUM_ACCESS_LIST *a, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (a == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(a, sizeof(RPC_ENUM_ACCESS_LIST));\r
+       PackGetStr(p, "HubName", a->HubName, sizeof(a->HubName));\r
+       a->NumAccess = PackGetIndexCount(p, "Protocol");\r
+       a->Accesses = ZeroMalloc(sizeof(ACCESS) * a->NumAccess);\r
+\r
+       for (i = 0;i < a->NumAccess;i++)\r
+       {\r
+               ACCESS *e = &a->Accesses[i];\r
+\r
+               InRpcAccessEx(e, p, i);\r
+       }\r
+}\r
+void OutRpcEnumAccessList(PACK *p, RPC_ENUM_ACCESS_LIST *a)\r
+{\r
+       UINT i;\r
+       PackAddStr(p, "HubName", a->HubName);\r
+       // 引数チェック\r
+       if (a == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 0;i < a->NumAccess;i++)\r
+       {\r
+               ACCESS *e = &a->Accesses[i];\r
+\r
+               OutRpcAccessEx(p, e, i, a->NumAccess);\r
+       }\r
+}\r
+void FreeRpcEnumAccessList(RPC_ENUM_ACCESS_LIST *a)\r
+{\r
+       // 引数チェック\r
+       if (a == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(a->Accesses);\r
+}\r
+\r
+// AUTHDATA\r
+void *InRpcAuthData(PACK *p, UINT *authtype)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       AUTHPASSWORD *pw;\r
+       AUTHUSERCERT *usercert;\r
+       AUTHROOTCERT *rootcert;\r
+       AUTHRADIUS *radius;\r
+       AUTHNT *nt;\r
+       BUF *b;\r
+       // 引数チェック\r
+       if (p == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+       if (authtype == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       *authtype = PackGetInt(p, "AuthType");\r
+\r
+       switch (*authtype)\r
+       {\r
+       case AUTHTYPE_PASSWORD:\r
+               pw = ZeroMalloc(sizeof(AUTHPASSWORD));\r
+               PackGetData2(p, "HashedKey", pw->HashedKey, sizeof(pw->HashedKey));\r
+               return pw;\r
+\r
+       case AUTHTYPE_USERCERT:\r
+               usercert = ZeroMalloc(sizeof(AUTHUSERCERT));\r
+               usercert->UserX = PackGetX(p, "UserX");\r
+               return usercert;\r
+\r
+       case AUTHTYPE_ROOTCERT:\r
+               rootcert = ZeroMalloc(sizeof(AUTHROOTCERT));\r
+               b = PackGetBuf(p, "Serial");\r
+               if (b != NULL)\r
+               {\r
+                       rootcert->Serial = NewXSerial(b->Buf, b->Size);\r
+                       FreeBuf(b);\r
+               }\r
+               if (PackGetUniStr(p, "CommonName", tmp, sizeof(tmp)))\r
+               {\r
+                       rootcert->CommonName = CopyUniStr(tmp);\r
+               }\r
+               return rootcert;\r
+\r
+       case AUTHTYPE_RADIUS:\r
+               radius = ZeroMalloc(sizeof(AUTHRADIUS));\r
+               if (PackGetUniStr(p, "RadiusUsername", tmp, sizeof(tmp)))\r
+               {\r
+                       radius->RadiusUsername = CopyUniStr(tmp);\r
+               }\r
+               else\r
+               {\r
+                       radius->RadiusUsername = CopyUniStr(L"");\r
+               }\r
+               return radius;\r
+\r
+       case AUTHTYPE_NT:\r
+               nt = ZeroMalloc(sizeof(AUTHNT));\r
+               if (PackGetUniStr(p, "NtUsername", tmp, sizeof(tmp)))\r
+               {\r
+                       nt->NtUsername = CopyUniStr(tmp);\r
+               }\r
+               else\r
+               {\r
+                       nt->NtUsername = CopyUniStr(L"");\r
+               }\r
+               return nt;\r
+       }\r
+\r
+       return NULL;\r
+}\r
+void OutRpcAuthData(PACK *p, void *authdata, UINT authtype)\r
+{\r
+       AUTHPASSWORD *pw = authdata;\r
+       AUTHUSERCERT *usercert = authdata;\r
+       AUTHROOTCERT *rootcert = authdata;\r
+       AUTHRADIUS *radius = authdata;\r
+       AUTHNT *nt = authdata;\r
+       // 引数チェック\r
+       if (p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddInt(p, "AuthType", authtype);\r
+\r
+       switch (authtype)\r
+       {\r
+       case AUTHTYPE_PASSWORD:\r
+               PackAddData(p, "HashedKey", pw->HashedKey, sizeof(pw->HashedKey));\r
+               break;\r
+\r
+       case AUTHTYPE_USERCERT:\r
+               PackAddX(p, "UserX", usercert->UserX);\r
+               break;\r
+\r
+       case AUTHTYPE_ROOTCERT:\r
+               if (rootcert->Serial != NULL)\r
+               {\r
+                       PackAddData(p, "Serial", rootcert->Serial->data, rootcert->Serial->size);\r
+               }\r
+               if (rootcert->CommonName != NULL)\r
+               {\r
+                       PackAddUniStr(p, "CommonName", rootcert->CommonName);\r
+               }\r
+               break;\r
+\r
+       case AUTHTYPE_RADIUS:\r
+               PackAddUniStr(p, "RadiusUsername", radius->RadiusUsername);\r
+               break;\r
+\r
+       case AUTHTYPE_NT:\r
+               PackAddUniStr(p, "NtUsername", nt->NtUsername);\r
+               break;\r
+       }\r
+}\r
+void FreeRpcAuthData(void *authdata, UINT authtype)\r
+{\r
+       FreeAuthData(authtype, authdata);\r
+}\r
+\r
+// RPC_SET_USER\r
+void InRpcSetUser(RPC_SET_USER *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_SET_USER));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       PackGetStr(p, "Name", t->Name, sizeof(t->Name));\r
+       PackGetStr(p, "GroupName", t->GroupName, sizeof(t->GroupName));\r
+       PackGetUniStr(p, "Realname", t->Realname, sizeof(t->Realname));\r
+       PackGetUniStr(p, "Note", t->Note, sizeof(t->Note));\r
+       t->CreatedTime = PackGetInt64(p, "CreatedTime");\r
+       t->UpdatedTime = PackGetInt64(p, "UpdatedTime");\r
+       t->ExpireTime = PackGetInt64(p, "ExpireTime");\r
+       t->AuthData = InRpcAuthData(p, &t->AuthType);\r
+       t->NumLogin = PackGetInt(p, "NumLogin");\r
+       InRpcTraffic(&t->Traffic, p);\r
+\r
+       if (PackGetBool(p, "UsePolicy"))\r
+       {\r
+               t->Policy = ZeroMalloc(sizeof(POLICY));\r
+               InRpcPolicy(t->Policy, p);\r
+       }\r
+}\r
+\r
+void OutRpcSetUser(PACK *p, RPC_SET_USER *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddStr(p, "Name", t->Name);\r
+       PackAddStr(p, "GroupName", t->GroupName);\r
+       PackAddUniStr(p, "Realname", t->Realname);\r
+       PackAddUniStr(p, "Note", t->Note);\r
+       PackAddInt64(p, "CreatedTime", t->CreatedTime);\r
+       PackAddInt64(p, "UpdatedTime", t->UpdatedTime);\r
+       PackAddInt64(p, "ExpireTime", t->ExpireTime);\r
+       OutRpcAuthData(p, t->AuthData, t->AuthType);\r
+       PackAddInt(p, "NumLogin", t->NumLogin);\r
+       OutRpcTraffic(p, &t->Traffic);\r
+\r
+       if (t->Policy != NULL)\r
+       {\r
+               PackAddBool(p, "UsePolicy", true);\r
+               OutRpcPolicy(p, t->Policy);\r
+       }\r
+}\r
+void FreeRpcSetUser(RPC_SET_USER *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       FreeRpcAuthData(t->AuthData, t->AuthType);\r
+       if (t->Policy)\r
+       {\r
+               Free(t->Policy);\r
+       }\r
+}\r
+\r
+// RPC_ENUM_USER\r
+void InRpcEnumUser(RPC_ENUM_USER *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_USER));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->NumUser = PackGetIndexCount(p, "Name");\r
+       t->Users = ZeroMalloc(sizeof(RPC_ENUM_USER_ITEM) * t->NumUser);\r
+\r
+       for (i = 0;i < t->NumUser;i++)\r
+       {\r
+               RPC_ENUM_USER_ITEM *e = &t->Users[i];\r
+\r
+               PackGetStrEx(p, "Name", e->Name, sizeof(e->Name), i);\r
+               PackGetStrEx(p, "GroupName", e->GroupName, sizeof(e->GroupName), i);\r
+               PackGetUniStrEx(p, "Realname", e->Realname, sizeof(e->Realname), i);\r
+               PackGetUniStrEx(p, "Note", e->Note, sizeof(e->Note), i);\r
+               e->AuthType = PackGetIntEx(p, "AuthType", i);\r
+               e->LastLoginTime = PackGetInt64Ex(p, "LastLoginTime", i);\r
+               e->NumLogin = PackGetIntEx(p, "NumLogin", i);\r
+               e->DenyAccess = PackGetBoolEx(p, "DenyAccess", i);\r
+       }\r
+}\r
+void OutRpcEnumUser(PACK *p, RPC_ENUM_USER *t)\r
+{\r
+       UINT i;\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 0;i < t->NumUser;i++)\r
+       {\r
+               RPC_ENUM_USER_ITEM *e = &t->Users[i];\r
+\r
+               PackAddStrEx(p, "Name", e->Name, i, t->NumUser);\r
+               PackAddStrEx(p, "GroupName", e->GroupName, i, t->NumUser);\r
+               PackAddUniStrEx(p, "Realname", e->Realname, i, t->NumUser);\r
+               PackAddUniStrEx(p, "Note", e->Note, i, t->NumUser);\r
+               PackAddIntEx(p, "AuthType", e->AuthType, i, t->NumUser);\r
+               PackAddInt64Ex(p, "LastLoginTime", e->LastLoginTime, i, t->NumUser);\r
+               PackAddIntEx(p, "NumLogin", e->NumLogin, i, t->NumUser);\r
+               PackAddBoolEx(p, "DenyAccess", e->DenyAccess, i, t->NumUser);\r
+       }\r
+}\r
+void FreeRpcEnumUser(RPC_ENUM_USER *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Users);\r
+}\r
+\r
+// RPC_SET_GROUP\r
+void InRpcSetGroup(RPC_SET_GROUP *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_SET_GROUP));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       PackGetStr(p, "Name", t->Name, sizeof(t->Name));\r
+       PackGetUniStr(p, "Realname", t->Realname, sizeof(t->Realname));\r
+       PackGetUniStr(p, "Note", t->Note, sizeof(t->Note));\r
+       InRpcTraffic(&t->Traffic, p);\r
+\r
+       if (PackGetBool(p, "UsePolicy"))\r
+       {\r
+               t->Policy = ZeroMalloc(sizeof(POLICY));\r
+               InRpcPolicy(t->Policy, p);\r
+       }\r
+}\r
+void OutRpcSetGroup(PACK *p, RPC_SET_GROUP *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddStr(p, "Name", t->Name);\r
+       PackAddUniStr(p, "Realname", t->Realname);\r
+       PackAddUniStr(p, "Note", t->Note);\r
+       OutRpcTraffic(p, &t->Traffic);\r
+\r
+       if (t->Policy != NULL)\r
+       {\r
+               PackAddBool(p, "UsePolicy", true);\r
+               OutRpcPolicy(p, t->Policy);\r
+       }\r
+}\r
+void FreeRpcSetGroup(RPC_SET_GROUP *t)\r
+{\r
+       Free(t->Policy);\r
+}\r
+\r
+// RPC_ENUM_GROUP\r
+void InRpcEnumGroup(RPC_ENUM_GROUP *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_GROUP));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->NumGroup = PackGetIndexCount(p, "Name");\r
+       t->Groups = ZeroMalloc(sizeof(RPC_ENUM_GROUP_ITEM) * t->NumGroup);\r
+\r
+       for (i = 0;i < t->NumGroup;i++)\r
+       {\r
+               RPC_ENUM_GROUP_ITEM *e = &t->Groups[i];\r
+\r
+               PackGetStrEx(p, "Name", e->Name, sizeof(e->Name), i);\r
+               PackGetUniStrEx(p, "Realname", e->Realname, sizeof(e->Realname), i);\r
+               PackGetUniStrEx(p, "Note", e->Note, sizeof(e->Note), i);\r
+               e->NumUsers = PackGetIntEx(p, "NumUsers", i);\r
+               e->DenyAccess = PackGetBoolEx(p, "DenyAccess", i);\r
+       }\r
+}\r
+void OutRpcEnumGroup(PACK *p, RPC_ENUM_GROUP *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+\r
+       for (i = 0;i < t->NumGroup;i++)\r
+       {\r
+               RPC_ENUM_GROUP_ITEM *e = &t->Groups[i];\r
+\r
+               PackAddStrEx(p, "Name", e->Name, i, t->NumGroup);\r
+               PackAddUniStrEx(p, "Realname", e->Realname, i, t->NumGroup);\r
+               PackAddUniStrEx(p, "Note", e->Note, i, t->NumGroup);\r
+               PackAddIntEx(p, "NumUsers", e->NumUsers, i, t->NumGroup);\r
+               PackAddBoolEx(p, "DenyAccess", e->DenyAccess, i, t->NumGroup);\r
+       }\r
+}\r
+void FreeRpcEnumGroup(RPC_ENUM_GROUP *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Groups);\r
+}\r
+\r
+// RPC_DELETE_USER\r
+void InRpcDeleteUser(RPC_DELETE_USER *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_DELETE_USER));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       PackGetStr(p, "Name", t->Name, sizeof(t->Name));\r
+}\r
+void OutRpcDeleteUser(PACK *p, RPC_DELETE_USER *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddStr(p, "Name", t->Name);\r
+}\r
+\r
+// RPC_ENUM_SESSION\r
+void InRpcEnumSession(RPC_ENUM_SESSION *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_SESSION));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->NumSession = PackGetIndexCount(p, "Name");\r
+       t->Sessions = ZeroMalloc(sizeof(RPC_ENUM_SESSION_ITEM) * t->NumSession);\r
+\r
+       for (i = 0;i < t->NumSession;i++)\r
+       {\r
+               RPC_ENUM_SESSION_ITEM *e = &t->Sessions[i];\r
+\r
+               PackGetStrEx(p, "Name", e->Name, sizeof(e->Name), i);\r
+               PackGetStrEx(p, "Username", e->Username, sizeof(e->Username), i);\r
+               e->Ip = PackGetIntEx(p, "Ip", i);\r
+               PackGetStrEx(p, "Hostname", e->Hostname, sizeof(e->Hostname), i);\r
+               e->MaxNumTcp = PackGetIntEx(p, "MaxNumTcp", i);\r
+               e->CurrentNumTcp = PackGetIntEx(p, "CurrentNumTcp", i);\r
+               e->PacketSize = PackGetInt64Ex(p, "PacketSize", i);\r
+               e->PacketNum = PackGetInt64Ex(p, "PacketNum", i);\r
+               e->RemoteSession = PackGetBoolEx(p, "RemoteSession", i);\r
+               e->LinkMode = PackGetBoolEx(p, "LinkMode", i);\r
+               e->SecureNATMode = PackGetBoolEx(p, "SecureNATMode", i);\r
+               e->BridgeMode = PackGetBoolEx(p, "BridgeMode", i);\r
+               e->Layer3Mode = PackGetBoolEx(p, "Layer3Mode", i);\r
+               e->Client_BridgeMode = PackGetBoolEx(p, "Client_BridgeMode", i);\r
+               e->Client_MonitorMode = PackGetBoolEx(p, "Client_MonitorMode", i);\r
+               PackGetStrEx(p, "RemoteHostname", e->RemoteHostname, sizeof(e->RemoteHostname), i);\r
+               e->VLanId = PackGetIntEx(p, "VLanId", i);\r
+               PackGetDataEx2(p, "UniqueId", e->UniqueId, sizeof(e->UniqueId), i);\r
+       }\r
+}\r
+void OutRpcEnumSession(PACK *p, RPC_ENUM_SESSION *t)\r
+{\r
+       UINT i;\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 0;i < t->NumSession;i++)\r
+       {\r
+               RPC_ENUM_SESSION_ITEM *e = &t->Sessions[i];\r
+\r
+               PackAddStrEx(p, "Name", e->Name, i, t->NumSession);\r
+               PackAddStrEx(p, "Username", e->Username, i, t->NumSession);\r
+               PackAddIp32Ex(p, "Ip", e->Ip, i, t->NumSession);\r
+               PackAddStrEx(p, "Hostname", e->Hostname, i, t->NumSession);\r
+               PackAddIntEx(p, "MaxNumTcp", e->MaxNumTcp, i, t->NumSession);\r
+               PackAddIntEx(p, "CurrentNumTcp", e->CurrentNumTcp, i, t->NumSession);\r
+               PackAddInt64Ex(p, "PacketSize", e->PacketSize, i, t->NumSession);\r
+               PackAddInt64Ex(p, "PacketNum", e->PacketNum, i, t->NumSession);\r
+               PackAddBoolEx(p, "RemoteSession", e->RemoteSession, i, t->NumSession);\r
+               PackAddStrEx(p, "RemoteHostname", e->RemoteHostname, i, t->NumSession);\r
+               PackAddBoolEx(p, "LinkMode", e->LinkMode, i, t->NumSession);\r
+               PackAddBoolEx(p, "SecureNATMode", e->SecureNATMode, i, t->NumSession);\r
+               PackAddBoolEx(p, "BridgeMode", e->BridgeMode, i, t->NumSession);\r
+               PackAddBoolEx(p, "Layer3Mode", e->Layer3Mode, i, t->NumSession);\r
+               PackAddBoolEx(p, "Client_BridgeMode", e->Client_BridgeMode, i, t->NumSession);\r
+               PackAddBoolEx(p, "Client_MonitorMode", e->Client_MonitorMode, i, t->NumSession);\r
+               PackAddIntEx(p, "VLanId", e->VLanId, i, t->NumSession);\r
+               PackAddDataEx(p, "UniqueId", e->UniqueId, sizeof(e->UniqueId), i, t->NumSession);\r
+       }\r
+}\r
+void FreeRpcEnumSession(RPC_ENUM_SESSION *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->Sessions);\r
+}\r
+\r
+// RPC_KEY_PAIR\r
+void InRpcKeyPair(RPC_KEY_PAIR *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       t->Cert = PackGetX(p, "Cert");\r
+       t->Key = PackGetK(p, "Key");\r
+}\r
+void OutRpcKeyPair(PACK *p, RPC_KEY_PAIR *t)\r
+{\r
+       // 引数チェック\r
+       if (p == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddX(p, "Cert", t->Cert);\r
+       PackAddK(p, "Key", t->Key);\r
+}\r
+void FreeRpcKeyPair(RPC_KEY_PAIR *t)\r
+{\r
+       FreeX(t->Cert);\r
+       FreeK(t->Key);\r
+}\r
+\r
+// NODE_INFO\r
+void InRpcNodeInfo(NODE_INFO *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(NODE_INFO));\r
+       PackGetStr(p, "ClientProductName", t->ClientProductName, sizeof(t->ClientProductName));\r
+       PackGetStr(p, "ServerProductName", t->ServerProductName, sizeof(t->ServerProductName));\r
+       PackGetStr(p, "ClientOsName", t->ClientOsName, sizeof(t->ClientOsName));\r
+       PackGetStr(p, "ClientOsVer", t->ClientOsVer, sizeof(t->ClientOsVer));\r
+       PackGetStr(p, "ClientOsProductId", t->ClientOsProductId, sizeof(t->ClientOsProductId));\r
+       PackGetStr(p, "ClientHostname", t->ClientHostname, sizeof(t->ClientHostname));\r
+       PackGetStr(p, "ServerHostname", t->ServerHostname, sizeof(t->ServerHostname));\r
+       PackGetStr(p, "ProxyHostname", t->ProxyHostname, sizeof(t->ProxyHostname));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       PackGetData2(p, "UniqueId", t->UniqueId, sizeof(t->UniqueId));\r
+\r
+       t->ClientProductVer = PackGetInt(p, "ClientProductVer");\r
+       t->ClientProductBuild = PackGetInt(p, "ClientProductBuild");\r
+       t->ServerProductVer = PackGetInt(p, "ServerProductVer");\r
+       t->ServerProductBuild = PackGetInt(p, "ServerProductBuild");\r
+       t->ClientIpAddress = PackGetIp32(p, "ClientIpAddress");\r
+       PackGetData2(p, "ClientIpAddress6", t->ClientIpAddress6, sizeof(t->ClientIpAddress6));\r
+       t->ClientPort = PackGetInt(p, "ClientPort");\r
+       t->ServerIpAddress = PackGetIp32(p, "ServerIpAddress");\r
+       PackGetData2(p, "ServerIpAddress6", t->ServerIpAddress6, sizeof(t->ServerIpAddress6));\r
+       t->ServerPort = PackGetInt(p, "ServerPort2");\r
+       t->ProxyIpAddress = PackGetIp32(p, "ProxyIpAddress");\r
+       PackGetData2(p, "ProxyIpAddress6", t->ProxyIpAddress6, sizeof(t->ProxyIpAddress6));\r
+       t->ProxyPort = PackGetInt(p, "ProxyPort");\r
+}\r
+void OutRpcNodeInfo(PACK *p, NODE_INFO *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "ClientProductName", t->ClientProductName);\r
+       PackAddStr(p, "ServerProductName", t->ServerProductName);\r
+       PackAddStr(p, "ClientOsName", t->ClientOsName);\r
+       PackAddStr(p, "ClientOsVer", t->ClientOsVer);\r
+       PackAddStr(p, "ClientOsProductId", t->ClientOsProductId);\r
+       PackAddStr(p, "ClientHostname", t->ClientHostname);\r
+       PackAddStr(p, "ServerHostname", t->ServerHostname);\r
+       PackAddStr(p, "ProxyHostname", t->ProxyHostname);\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddData(p, "UniqueId", t->UniqueId, sizeof(t->UniqueId));\r
+\r
+       PackAddInt(p, "ClientProductVer", t->ClientProductVer);\r
+       PackAddInt(p, "ClientProductBuild", t->ClientProductBuild);\r
+       PackAddInt(p, "ServerProductVer", t->ServerProductVer);\r
+       PackAddInt(p, "ServerProductBuild", t->ServerProductBuild);\r
+       PackAddIp32(p, "ClientIpAddress", t->ClientIpAddress);\r
+       PackAddData(p, "ClientIpAddress6", t->ClientIpAddress6, sizeof(t->ClientIpAddress6));\r
+       PackAddInt(p, "ClientPort", t->ClientPort);\r
+       PackAddIp32(p, "ServerIpAddress", t->ServerIpAddress);\r
+       PackAddData(p, "ServerIpAddress6", t->ServerIpAddress6, sizeof(t->ServerIpAddress6));\r
+       PackAddInt(p, "ServerPort2", t->ServerPort);\r
+       PackAddIp32(p, "ProxyIpAddress", t->ProxyIpAddress);\r
+       PackAddData(p, "ProxyIpAddress6", t->ProxyIpAddress6, sizeof(t->ProxyIpAddress6));\r
+       PackAddInt(p, "ProxyPort", t->ProxyPort);\r
+}\r
+\r
+// RPC_SESSION_STATUS\r
+void InRpcSessionStatus(RPC_SESSION_STATUS *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_SESSION_STATUS));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       PackGetStr(p, "Name", t->Name, sizeof(t->Name));\r
+       PackGetStr(p, "Username", t->Username, sizeof(t->Username));\r
+       PackGetStr(p, "GroupName", t->GroupName, sizeof(t->GroupName));\r
+       PackGetStr(p, "RealUsername", t->RealUsername, sizeof(t->RealUsername));\r
+       t->ClientIp = PackGetIp32(p, "SessionStatus_ClientIp");\r
+       PackGetData2(p, "SessionStatus_ClientIp6", t->ClientIp6, sizeof(t->ClientIp6));\r
+       PackGetStr(p, "SessionStatus_ClientHostName", t->ClientHostName, sizeof(t->ClientHostName));\r
+\r
+       InRpcClientGetConnectionStatus(&t->Status, p);\r
+       InRpcNodeInfo(&t->NodeInfo, p);\r
+}\r
+void OutRpcSessionStatus(PACK *p, RPC_SESSION_STATUS *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddStr(p, "Name", t->Name);\r
+       PackAddStr(p, "Username", t->Username);\r
+       PackAddStr(p, "GroupName", t->GroupName);\r
+       PackAddStr(p, "RealUsername", t->RealUsername);\r
+       PackAddIp32(p, "SessionStatus_ClientIp", t->ClientIp);\r
+       PackAddData(p, "SessionStatus_ClientIp6", t->ClientIp6, sizeof(t->ClientIp6));\r
+       PackAddStr(p, "SessionStatus_ClientHostName", t->ClientHostName);\r
+\r
+       OutRpcClientGetConnectionStatus(p, &t->Status);\r
+       OutRpcNodeInfo(p, &t->NodeInfo);\r
+}\r
+void FreeRpcSessionStatus(RPC_SESSION_STATUS *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       CiFreeClientGetConnectionStatus(&t->Status);\r
+}\r
+\r
+// RPC_DELETE_SESSION\r
+void InRpcDeleteSession(RPC_DELETE_SESSION *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_DELETE_SESSION));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       PackGetStr(p, "Name", t->Name, sizeof(t->Name));\r
+}\r
+void OutRpcDeleteSession(PACK *p, RPC_DELETE_SESSION *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddStr(p, "Name", t->Name);\r
+}\r
+\r
+// RPC_ENUM_MAC_TABLE\r
+void InRpcEnumMacTable(RPC_ENUM_MAC_TABLE *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_MAC_TABLE));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->NumMacTable = PackGetIndexCount(p, "SessionName");\r
+       t->MacTables = ZeroMalloc(sizeof(RPC_ENUM_MAC_TABLE_ITEM) * t->NumMacTable);\r
+\r
+       for (i = 0;i < t->NumMacTable;i++)\r
+       {\r
+               RPC_ENUM_MAC_TABLE_ITEM *e = &t->MacTables[i];\r
+\r
+               e->Key = PackGetIntEx(p, "Key", i);\r
+               PackGetStrEx(p, "SessionName", e->SessionName, sizeof(e->SessionName), i);\r
+               PackGetDataEx2(p, "MacAddress", e->MacAddress, sizeof(e->MacAddress), i);\r
+               e->VlanId = PackGetIntEx(p, "VlanId", i);\r
+               e->CreatedTime = PackGetInt64Ex(p, "CreatedTime", i);\r
+               e->UpdatedTime = PackGetInt64Ex(p, "UpdatedTime", i);\r
+               e->RemoteItem = PackGetBoolEx(p, "RemoteItem", i);\r
+               PackGetStrEx(p, "RemoteHostname", e->RemoteHostname, sizeof(e->RemoteHostname), i);\r
+       }\r
+}\r
+void OutRpcEnumMacTable(PACK *p, RPC_ENUM_MAC_TABLE *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+\r
+       for (i = 0;i < t->NumMacTable;i++)\r
+       {\r
+               RPC_ENUM_MAC_TABLE_ITEM *e = &t->MacTables[i];\r
+\r
+               PackAddIntEx(p, "Key", e->Key, i, t->NumMacTable);\r
+               PackAddStrEx(p, "SessionName", e->SessionName, i, t->NumMacTable);\r
+               PackAddDataEx(p, "MacAddress", e->MacAddress, sizeof(e->MacAddress), i, t->NumMacTable);\r
+               PackAddIntEx(p, "VlanId", e->VlanId, i, t->NumMacTable);\r
+               PackAddInt64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumMacTable);\r
+               PackAddInt64Ex(p, "UpdatedTime", e->UpdatedTime, i, t->NumMacTable);\r
+               PackAddBoolEx(p, "RemoteItem", e->RemoteItem, i, t->NumMacTable);\r
+               PackAddStrEx(p, "RemoteHostname", e->RemoteHostname, i, t->NumMacTable);\r
+       }\r
+}\r
+void FreeRpcEnumMacTable(RPC_ENUM_MAC_TABLE *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->MacTables);\r
+}\r
+\r
+// RPC_ENUM_IP_TABLE\r
+void InRpcEnumIpTable(RPC_ENUM_IP_TABLE *t, PACK *p)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_ENUM_IP_TABLE));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->NumIpTable = PackGetIndexCount(p, "SessionName");\r
+       t->IpTables = ZeroMalloc(sizeof(RPC_ENUM_IP_TABLE_ITEM) * t->NumIpTable);\r
+\r
+       for (i = 0;i < t->NumIpTable;i++)\r
+       {\r
+               RPC_ENUM_IP_TABLE_ITEM *e = &t->IpTables[i];\r
+\r
+               e->Key = PackGetIntEx(p, "Key", i);\r
+               PackGetStrEx(p, "SessionName", e->SessionName, sizeof(e->SessionName), i);\r
+               e->Ip = PackGetIp32Ex(p, "Ip", i);\r
+               if (PackGetIpEx(p, "IpV6", &e->IpV6, i) == false)\r
+               {\r
+                       UINTToIP(&e->IpV6, e->Ip);\r
+               }\r
+               e->DhcpAllocated = PackGetBoolEx(p, "DhcpAllocated", i);\r
+               e->CreatedTime = PackGetInt64Ex(p, "CreatedTime", i);\r
+               e->UpdatedTime = PackGetInt64Ex(p, "UpdatedTime", i);\r
+               e->RemoteItem = PackGetBoolEx(p, "RemoteItem", i);\r
+               PackGetStrEx(p, "RemoteHostname", e->RemoteHostname, sizeof(e->RemoteHostname), i);\r
+       }\r
+}\r
+void OutRpcEnumIpTable(PACK *p, RPC_ENUM_IP_TABLE *t)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+\r
+       for (i = 0;i < t->NumIpTable;i++)\r
+       {\r
+               RPC_ENUM_IP_TABLE_ITEM *e = &t->IpTables[i];\r
+\r
+               PackAddIntEx(p, "Key", e->Key, i, t->NumIpTable);\r
+               PackAddStrEx(p, "SessionName", e->SessionName, i, t->NumIpTable);\r
+               PackAddIp32Ex(p, "Ip", e->Ip, i, t->NumIpTable);\r
+               PackAddIpEx(p, "IpV6", &e->IpV6, i, t->NumIpTable);\r
+               PackAddBoolEx(p, "DhcpAllocated", e->DhcpAllocated, i, t->NumIpTable);\r
+               PackAddInt64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumIpTable);\r
+               PackAddInt64Ex(p, "UpdatedTime", e->UpdatedTime, i, t->NumIpTable);\r
+               PackAddBoolEx(p, "RemoteItem", e->RemoteItem, i, t->NumIpTable);\r
+               PackAddStrEx(p, "RemoteHostname", e->RemoteHostname, i, t->NumIpTable);\r
+       }\r
+}\r
+void FreeRpcEnumIpTable(RPC_ENUM_IP_TABLE *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(t->IpTables);\r
+}\r
+\r
+// RPC_DELETE_TABLE\r
+void InRpcDeleteTable(RPC_DELETE_TABLE *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_DELETE_TABLE));\r
+       PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));\r
+       t->Key = PackGetInt(p, "Key");\r
+}\r
+void OutRpcDeleteTable(PACK *p, RPC_DELETE_TABLE *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddStr(p, "HubName", t->HubName);\r
+       PackAddInt(p, "Key", t->Key);\r
+}\r
+\r
+// RPC_ENUM_IP_TABLE の結合\r
+void AdjoinRpcEnumIpTable(RPC_ENUM_IP_TABLE *dest, RPC_ENUM_IP_TABLE *src)\r
+{\r
+       UINT old_num;\r
+       UINT i, n;\r
+       if (dest == NULL || src == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (src->NumIpTable == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       old_num = dest->NumIpTable;\r
+       dest->NumIpTable += src->NumIpTable;\r
+       dest->IpTables = ReAlloc(dest->IpTables, sizeof(RPC_ENUM_IP_TABLE_ITEM) * dest->NumIpTable);\r
+\r
+       n = 0;\r
+       for (i = old_num;i < dest->NumIpTable;i++)\r
+       {\r
+               Copy(&dest->IpTables[i], &src->IpTables[n++], sizeof(RPC_ENUM_IP_TABLE_ITEM));\r
+       }\r
+}\r
+\r
+// RPC_ENUM_MAC_TABLE の結合\r
+void AdjoinRpcEnumMacTable(RPC_ENUM_MAC_TABLE *dest, RPC_ENUM_MAC_TABLE *src)\r
+{\r
+       UINT old_num;\r
+       UINT i, n;\r
+       if (dest == NULL || src == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (src->NumMacTable == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       old_num = dest->NumMacTable;\r
+       dest->NumMacTable += src->NumMacTable;\r
+       dest->MacTables = ReAlloc(dest->MacTables, sizeof(RPC_ENUM_MAC_TABLE_ITEM) * dest->NumMacTable);\r
+\r
+       n = 0;\r
+       for (i = old_num;i < dest->NumMacTable;i++)\r
+       {\r
+               Copy(&dest->MacTables[i], &src->MacTables[n++], sizeof(RPC_ENUM_MAC_TABLE_ITEM));\r
+       }\r
+}\r
+\r
+// RPC_ENUM_SESSION の結合\r
+void AdjoinRpcEnumSession(RPC_ENUM_SESSION *dest, RPC_ENUM_SESSION *src)\r
+{\r
+       UINT old_num;\r
+       UINT i, n;\r
+       if (dest == NULL || src == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (src->NumSession == 0)\r
+       {\r
+               return;\r
+       }\r
+\r
+       old_num = dest->NumSession;\r
+       dest->NumSession += src->NumSession;\r
+       dest->Sessions = ReAlloc(dest->Sessions, sizeof(RPC_ENUM_SESSION_ITEM) * dest->NumSession);\r
+\r
+       n = 0;\r
+       for (i = old_num;i < dest->NumSession;i++)\r
+       {\r
+               Copy(&dest->Sessions[i], &src->Sessions[n++], sizeof(RPC_ENUM_SESSION_ITEM));\r
+       }\r
+}\r
+\r
+// RPC_KEEP\r
+void InRpcKeep(RPC_KEEP *t, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(RPC_KEEP));\r
+       t->UseKeepConnect = PackGetBool(p, "UseKeepConnect");\r
+       PackGetStr(p, "KeepConnectHost", t->KeepConnectHost, sizeof(t->KeepConnectHost));\r
+       t->KeepConnectPort = PackGetInt(p, "KeepConnectPort");\r
+       t->KeepConnectProtocol = PackGetInt(p, "KeepConnectProtocol");\r
+       t->KeepConnectInterval = PackGetInt(p, "KeepConnectInterval");\r
+}\r
+void OutRpcKeep(PACK *p, RPC_KEEP *t)\r
+{\r
+       // 引数チェック\r
+       if (t == NULL || p == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddBool(p, "UseKeepConnect", t->UseKeepConnect);\r
+       PackAddStr(p, "KeepConnectHost", t->KeepConnectHost);\r
+       PackAddInt(p, "KeepConnectPort", t->KeepConnectPort);\r
+       PackAddInt(p, "KeepConnectProtocol", t->KeepConnectProtocol);\r
+       PackAddInt(p, "KeepConnectInterval", t->KeepConnectInterval);\r
+}\r
+\r
+// テスト RPC 関数\r
+UINT StTest(ADMIN *a, RPC_TEST *t)\r
+{\r
+       Format(t->StrValue, sizeof(t->StrValue), "%u", t->IntValue);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// RPC_TEST\r
+void InRpcTest(RPC_TEST *t, PACK *p)\r
+{\r
+       Zero(t, sizeof(RPC_TEST));\r
+       t->IntValue = PackGetInt(p, "IntValue");\r
+       PackGetStr(p, "StrValue", t->StrValue, sizeof(t->StrValue));\r
+}\r
+void OutRpcTest(PACK *p, RPC_TEST *t)\r
+{\r
+       PackAddInt(p, "IntValue", t->IntValue);\r
+       PackAddStr(p, "StrValue", t->StrValue);\r
+}\r
+void FreeRpcTest(RPC_TEST *t)\r
+{\r
+}\r
+\r
+// 管理用呼び出し\r
+PACK *AdminCall(RPC *rpc, char *function_name, PACK *p)\r
+{\r
+       // 引数チェック\r
+       if (rpc == NULL || function_name == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+       if (p == NULL)\r
+       {\r
+               p = NewPack();\r
+       }\r
+\r
+       return RpcCall(rpc, function_name, p);\r
+}\r
+\r
+// 管理用コネクションのソースアドレスが許可されているかどうか調べる\r
+bool CheckAdminSourceAddress(SOCK *sock, char *hubname)\r
+{\r
+       BUF *b;\r
+       char *s;\r
+       bool ok = false;\r
+       // 引数チェック\r
+       if (sock == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       b = ReadDump(ADMINIP_TXT);\r
+       if (b == NULL)\r
+       {\r
+               return true;\r
+       }\r
+\r
+       while (true)\r
+       {\r
+               UINT i;\r
+               TOKEN_LIST *t;\r
+               IP ip;\r
+               s = CfgReadNextLine(b);\r
+\r
+               if (s == NULL)\r
+               {\r
+                       break;\r
+               }\r
+\r
+               Trim(s);\r
+\r
+               i = SearchStrEx(s, "//", 0, false);\r
+               if (i != INFINITE)\r
+               {\r
+                       s[i] = 0;\r
+               }\r
+\r
+               i = SearchStrEx(s, "#", 0, false);\r
+               if (i != INFINITE)\r
+               {\r
+                       s[i] = 0;\r
+               }\r
+\r
+               Trim(s);\r
+\r
+               t = ParseToken(s, " \t");\r
+               if (t != NULL)\r
+               {\r
+                       if (t->NumTokens >= 1)\r
+                       {\r
+                               if (t->NumTokens == 1 || StrCmpi(hubname, t->Token[1]) == 0)\r
+                               {\r
+                                       if (StrToIP(&ip, t->Token[0]))\r
+                                       {\r
+                                               if (CmpIpAddr(&sock->RemoteIP, &ip) == 0)\r
+                                               {\r
+                                                       ok = true;\r
+                                               }\r
+                                       }\r
+\r
+                                       if (StrCmpi(t->Token[0], "*") == 0)\r
+                                       {\r
+                                               ok = true;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       FreeToken(t);\r
+               }\r
+\r
+               Free(s);\r
+       }\r
+\r
+       FreeBuf(b);\r
+\r
+       return ok;\r
+}\r
+\r
+// 管理用コネクション受け入れ\r
+UINT AdminAccept(CONNECTION *c, PACK *p)\r
+{\r
+       ADMIN *a;\r
+       UCHAR secure_password[SHA1_SIZE];\r
+       UCHAR null_password[SHA1_SIZE];\r
+       UCHAR secure_null_password[SHA1_SIZE];\r
+       char hubname[MAX_HUBNAME_LEN + 1];\r
+       CEDAR *cedar;\r
+       SOCK *sock;\r
+       RPC *rpc;\r
+       UINT err;\r
+       RPC_WINVER ver;\r
+       // 引数チェック\r
+       if (c == NULL || p == NULL)\r
+       {\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       cedar = c->Cedar;\r
+       sock = c->FirstSock;\r
+\r
+       // クライアント OS を取得\r
+       InRpcWinVer(&ver, p);\r
+\r
+       // HUB 名を取得\r
+       if (PackGetStr(p, "hubname", hubname, sizeof(hubname)) == false)\r
+       {\r
+               // HUB 名無し\r
+               StrCpy(hubname, sizeof(hubname), "");\r
+       }\r
+\r
+       // IP アドレスを見て許可するかどうか決める\r
+       if (CheckAdminSourceAddress(sock, hubname) == false)\r
+       {\r
+               SLog(c->Cedar, "LA_IP_DENIED", c->Name);\r
+               return ERR_IP_ADDRESS_DENIED;\r
+       }\r
+\r
+       // パスワードを取得\r
+       if (PackGetDataSize(p, "secure_password") != SHA1_SIZE)\r
+       {\r
+               // プロトコルエラー\r
+               return ERR_PROTOCOL_ERROR;\r
+       }\r
+       PackGetData(p, "secure_password", secure_password);\r
+\r
+       if (StrLen(hubname) == 0)\r
+       {\r
+               // サーバー管理モード接続\r
+               SLog(c->Cedar, "LA_CONNECTED_1", c->Name);\r
+       }\r
+       else\r
+       {\r
+               // 仮想 HUB 管理モード接続\r
+               if (cedar->Server != NULL && cedar->Server->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+               {\r
+                       // クラスタ メンバには仮想 HUB 管理モードで接続することはできない\r
+                       return ERR_NOT_ENOUGH_RIGHT;\r
+               }\r
+               SLog(c->Cedar, "LA_CONNECTED_2", c->Name, hubname);\r
+       }\r
+\r
+       // パスワードチェック\r
+       err = AdminCheckPassword(cedar, c->Random, secure_password,\r
+               StrLen(hubname) != 0 ? hubname : NULL);\r
+\r
+       if (err != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               SLog(c->Cedar, "LA_ERROR", c->Name, GetUniErrorStr(err), err);\r
+               return err;\r
+       }\r
+\r
+       SLog(c->Cedar, "LA_OK", c->Name);\r
+\r
+       HashAdminPassword(null_password, "");\r
+       SecurePassword(secure_null_password, null_password, c->Random);\r
+\r
+       if (Cmp(secure_null_password, secure_password, SHA1_SIZE) == 0)\r
+       {\r
+               if (sock->RemoteIP.addr[0] != 127)\r
+               {\r
+                       // パスワードが空であるがリモート接続しようとした\r
+                       // (仮想 HUB 管理モードのみ)\r
+                       if (StrLen(hubname) != 0)\r
+                       {\r
+                               return ERR_NULL_PASSWORD_LOCAL_ONLY;\r
+                       }\r
+               }\r
+       }\r
+\r
+       // 成功結果を送信\r
+       p = NewPack();\r
+       HttpServerSend(sock, p);\r
+       FreePack(p);\r
+\r
+       // ADMIN 構造体を作成\r
+       a = ZeroMalloc(sizeof(ADMIN));\r
+       a->ServerAdmin = ((StrLen(hubname) == 0) ? true : false);\r
+       a->HubName = (StrLen(hubname) != 0 ? hubname : NULL);\r
+       a->Server = c->Cedar->Server;\r
+       a->ClientBuild = c->ClientBuild;\r
+\r
+       Copy(&a->ClientWinVer, &ver, sizeof(RPC_WINVER));\r
+\r
+       // タイムアウト設定\r
+       SetTimeout(sock, INFINITE);\r
+\r
+       // RPC サーバー\r
+       rpc = StartRpcServer(sock, AdminDispatch, a);\r
+\r
+       a->Rpc = rpc;\r
+\r
+       SLog(c->Cedar, "LA_RPC_START", c->Name, rpc->Name);\r
+\r
+       RpcServer(rpc);\r
+       RpcFree(rpc);\r
+\r
+       if (a->LogFileList != NULL)\r
+       {\r
+               // キャッシュされたログファイル列挙リストがあれば解放する\r
+               FreeEnumLogFile(a->LogFileList);\r
+       }\r
+\r
+       // ADMIN 構造体を解放\r
+       Free(a);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// 管理者パスワードのチェック\r
+UINT AdminCheckPassword(CEDAR *c, void *random, void *secure_password, char *hubname)\r
+{\r
+       UCHAR check[SHA1_SIZE];\r
+       // 引数チェック\r
+       if (c == NULL || random == NULL || secure_password == NULL)\r
+       {\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       if (hubname == NULL || StrLen(hubname) == 0)\r
+       {\r
+               // サーバー全体の管理モード\r
+               Lock(c->lock);\r
+               {\r
+                       SecurePassword(check, c->Server->HashedPassword, random);\r
+               }\r
+               Unlock(c->lock);\r
+\r
+               if (Cmp(check, secure_password, SHA1_SIZE) != 0)\r
+               {\r
+                       // パスワード相違\r
+                       return ERR_ACCESS_DENIED;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               HUB *h;\r
+\r
+#if    0\r
+               if (c->Server->ServerType == SERVER_TYPE_FARM_MEMBER)\r
+               {\r
+                       // ファームメンバの場合は HUB 管理モードで接続できない\r
+                       return ERR_FARM_MEMBER_HUB_ADMIN;\r
+               }\r
+#endif\r
+\r
+               // HUB 管理モード\r
+               LockHubList(c);\r
+               {\r
+                       h = GetHub(c, hubname);\r
+               }\r
+               UnlockHubList(c);\r
+\r
+               if (h == NULL)\r
+               {\r
+                       // HUB が見つからない\r
+                       return ERR_HUB_NOT_FOUND;\r
+               }\r
+\r
+               Lock(h->lock);\r
+               {\r
+                       SecurePassword(check, h->HashedPassword, random);\r
+               }\r
+               Unlock(h->lock);\r
+\r
+               ReleaseHub(h);\r
+\r
+               if (Cmp(check, secure_password, SHA1_SIZE) != 0)\r
+               {\r
+                       // パスワード相違\r
+                       return ERR_ACCESS_DENIED;\r
+               }\r
+       }\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// 管理者パスワードのハッシュ\r
+void HashAdminPassword(void *hash, char *password)\r
+{\r
+       // 引数チェック\r
+       if (hash == NULL || password == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Hash(hash, password, StrLen(password), true);\r
+}\r
+\r
+// 管理用コネクション切断\r
+void AdminDisconnect(RPC *rpc)\r
+{\r
+       SESSION *s;\r
+       SOCK *sock;\r
+       // 引数チェック\r
+       if (rpc == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       s = (SESSION *)rpc->Param;\r
+       sock = rpc->Sock;\r
+\r
+       EndRpc(rpc);\r
+\r
+       Disconnect(sock);\r
+       ReleaseSession(s);\r
+}\r
+\r
+// 管理接続メイン\r
+SESSION *AdminConnectMain(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, void *hashed_password, UINT *err, char *client_name, void *hWnd)\r
+{\r
+       UCHAR secure_password[SHA1_SIZE];\r
+       SESSION *s;\r
+       SOCK *sock;\r
+       PACK *p;\r
+       RPC_WINVER ver;\r
+       // 接続\r
+       s = NewRpcSessionEx2(cedar, o, err, client_name, hWnd);\r
+       if (s == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       // ソケット取得\r
+       sock = s->Connection->FirstSock;\r
+\r
+       // 接続メソッド作成\r
+       p = NewPack();\r
+\r
+       PackAddClientVersion(p, s->Connection);\r
+\r
+       PackAddStr(p, "method", "admin");\r
+\r
+       // クライアント Windows バージョン\r
+       GetWinVer(&ver);\r
+       OutRpcWinVer(p, &ver);\r
+\r
+       // セキュアパスワード\r
+       SecurePassword(secure_password, hashed_password, s->Connection->Random);\r
+\r
+       PackAddData(p, "secure_password", secure_password, sizeof(secure_password));\r
+\r
+       // HUB 名\r
+       if (hubname != NULL)\r
+       {\r
+               PackAddStr(p, "hubname", hubname);\r
+       }\r
+\r
+       if (HttpClientSend(sock, p) == false)\r
+       {\r
+               // 切断\r
+               FreePack(p);\r
+               ReleaseSession(s);\r
+               *err = ERR_DISCONNECTED;\r
+               return NULL;\r
+       }\r
+\r
+       FreePack(p);\r
+\r
+       p = HttpClientRecv(sock);\r
+       if (p == NULL)\r
+       {\r
+               // 切断\r
+               ReleaseSession(s);\r
+               *err = ERR_DISCONNECTED;\r
+               return NULL;\r
+       }\r
+\r
+       if (GetErrorFromPack(p) != 0)\r
+       {\r
+               // エラー\r
+               ReleaseSession(s);\r
+               *err = GetErrorFromPack(p);\r
+               FreePack(p);\r
+               return NULL;\r
+       }\r
+\r
+       FreePack(p);\r
+\r
+       return s;\r
+}\r
+\r
+// 管理用コネクション接続\r
+RPC *AdminConnect(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, void *hashed_password, UINT *err)\r
+{\r
+       return AdminConnectEx(cedar, o, hubname, hashed_password, err, NULL);\r
+}\r
+RPC *AdminConnectEx(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, void *hashed_password, UINT *err, char *client_name)\r
+{\r
+       return AdminConnectEx2(cedar, o, hubname, hashed_password, err, client_name, NULL);\r
+}\r
+RPC *AdminConnectEx2(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, void *hashed_password, UINT *err, char *client_name, void *hWnd)\r
+{\r
+       SESSION *s;\r
+       SOCK *sock;\r
+       RPC *rpc;\r
+       // 引数チェック\r
+       if (cedar == NULL || o == NULL || hashed_password == NULL || err == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       if (client_name == NULL)\r
+       {\r
+               client_name = CEDAR_MANAGER_STR;\r
+       }\r
+\r
+       s = AdminConnectMain(cedar, o, hubname, hashed_password, err, client_name, hWnd);\r
+\r
+       if (s == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       sock = s->Connection->FirstSock;\r
+\r
+       // RPC 開始\r
+       rpc = StartRpcClient(sock, s);\r
+\r
+       rpc->IsVpnServer = true;\r
+       Copy(&rpc->VpnServerClientOption, o, sizeof(CLIENT_OPTION));\r
+       StrCpy(rpc->VpnServerHubName, sizeof(rpc->VpnServerHubName), hubname);\r
+       Copy(rpc->VpnServerHashedPassword, hashed_password, SHA1_SIZE);\r
+       StrCpy(rpc->VpnServerClientName, sizeof(rpc->VpnServerClientName), client_name);\r
+\r
+       // タイムアウト設定\r
+       SetTimeout(sock, INFINITE);\r
+\r
+       return rpc;\r
+}\r
+\r
+// 再接続\r
+UINT AdminReconnect(RPC *rpc)\r
+{\r
+       SESSION *s;\r
+       SOCK *sock;\r
+       CEDAR *cedar;\r
+       UINT err;\r
+       // 引数チェック\r
+       if (rpc == NULL || rpc->IsVpnServer == false)\r
+       {\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       s = (SESSION *)rpc->Param;\r
+       cedar = s->Cedar;\r
+       AddRef(cedar->ref);\r
+\r
+       sock = rpc->Sock;\r
+       Disconnect(sock);\r
+       ReleaseSock(sock);\r
+       ReleaseSession(s);\r
+       rpc->Param = NULL;\r
+\r
+       rpc->Sock = NULL;\r
+\r
+       s = AdminConnectMain(cedar, &rpc->VpnServerClientOption,\r
+               rpc->VpnServerHubName,\r
+               rpc->VpnServerHashedPassword,\r
+               &err,\r
+               rpc->VpnServerClientName, NULL);\r
+\r
+       ReleaseCedar(cedar);\r
+\r
+       if (s == NULL)\r
+       {\r
+               return err;\r
+       }\r
+\r
+       rpc->Param = s;\r
+       rpc->Sock = s->Connection->FirstSock;\r
+       AddRef(rpc->Sock->ref);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r