* tar xzf utvpn-src-unix-v101-7101-public-2010.06.27.tar.gz
[lab.git] / utvpn / utvpn-unix-v101-7101-public / src / Cedar / Command.c
diff --git a/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Command.c b/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Command.c
new file mode 100644 (file)
index 0000000..ff1adf1
--- /dev/null
@@ -0,0 +1,22416 @@
+// 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
+// Command.c\r
+// vpncmd コマンドライン管理ユーティリティ\r
+\r
+#include "CedarPch.h"\r
+\r
+// システムチェッカ定義\r
+typedef bool (CHECKER_PROC_DEF)();\r
+typedef struct CHECKER_PROC\r
+{\r
+       char *Title;\r
+       CHECKER_PROC_DEF *Proc;\r
+} CHECKER_PROC;\r
+\r
+static CHECKER_PROC checker_procs[] =\r
+{\r
+       {"CHECK_PROC_KERNEL", CheckKernel},\r
+       {"CHECK_PROC_MEMORY", CheckMemory},\r
+       {"CHECK_PROC_STRINGS", CheckStrings},\r
+       {"CHECK_PROC_FILESYSTEM", CheckFileSystem},\r
+       {"CHECK_PROC_THREAD", CheckThread},\r
+       {"CHECK_PROC_NETWORK", CheckNetwork},\r
+};\r
+\r
+typedef struct CHECK_NETWORK_1\r
+{\r
+       SOCK *ListenSocket;\r
+} CHECK_NETWORK_1;\r
+\r
+typedef struct CHECK_NETWORK_2\r
+{\r
+       SOCK *s;\r
+       X *x;\r
+       K *k;\r
+} CHECK_NETWORK_2;\r
+\r
+\r
+// TT_RESULT を RPC に変換\r
+void OutRpcTtResult(PACK *p, TT_RESULT *t)\r
+{\r
+       if (p == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       PackAddBool(p, "Raw", t->Raw);\r
+       PackAddBool(p, "Double", t->Double);\r
+       PackAddInt64(p, "NumBytesUpload", t->NumBytesUpload);\r
+       PackAddInt64(p, "NumBytesDownload", t->NumBytesDownload);\r
+       PackAddInt64(p, "NumBytesTotal", t->NumBytesTotal);\r
+       PackAddInt64(p, "Span", t->Span);\r
+       PackAddInt64(p, "BpsUpload", t->BpsUpload);\r
+       PackAddInt64(p, "BpsDownload", t->BpsDownload);\r
+       PackAddInt64(p, "BpsTotal", t->BpsTotal);\r
+}\r
+\r
+// RPC を TT_RESULT に変換\r
+void InRpcTtResult(PACK *p, TT_RESULT *t)\r
+{\r
+       if (p == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(TT_RESULT));\r
+\r
+       t->Raw = PackGetBool(p, "Raw");\r
+       t->Double = PackGetBool(p, "Double");\r
+       t->NumBytesUpload = PackGetInt64(p, "NumBytesUpload");\r
+       t->NumBytesDownload = PackGetInt64(p, "NumBytesDownload");\r
+       t->NumBytesTotal = PackGetInt64(p, "NumBytesTotal");\r
+       t->Span = PackGetInt64(p, "Span");\r
+       t->BpsUpload = PackGetInt64(p, "BpsUpload");\r
+       t->BpsDownload = PackGetInt64(p, "BpsDownload");\r
+       t->BpsTotal = PackGetInt64(p, "BpsTotal");\r
+}\r
+\r
+// Accept スレッド\r
+void CheckNetworkAcceptThread(THREAD *thread, void *param)\r
+{\r
+       CHECK_NETWORK_2 *c = (CHECK_NETWORK_2 *)param;\r
+       SOCK *s = c->s;\r
+       UINT i = 0;\r
+\r
+       if (StartSSL(s, c->x, c->k))\r
+       {\r
+               while (true)\r
+               {\r
+                       i++;\r
+                       if (Send(s, &i, sizeof(UINT), true) == 0)\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+\r
+       Disconnect(s);\r
+       ReleaseSock(s);\r
+}\r
+\r
+\r
+// Listen スレッド\r
+void CheckNetworkListenThread(THREAD *thread, void *param)\r
+{\r
+       CHECK_NETWORK_1 *c = (CHECK_NETWORK_1 *)param;\r
+       SOCK *s;\r
+       UINT i;\r
+       K *pub, *pri;\r
+       X *x;\r
+       LIST *o = NewList(NULL);\r
+       NAME *name = NewName(L"Test", L"Test", L"Test", L"JP", L"Ibaraki", L"Tsukuba");\r
+\r
+       RsaGen(&pri, &pub, 1024);\r
+       x = NewRootX(pub, pri, name, 1000, NULL);\r
+\r
+       FreeName(name);\r
+\r
+       for (i = 1025;;i++)\r
+       {\r
+               s = Listen(i);\r
+               if (s != NULL)\r
+               {\r
+                       break;\r
+               }\r
+       }\r
+\r
+       c->ListenSocket = s;\r
+       AddRef(s->ref);\r
+\r
+       NoticeThreadInit(thread);\r
+\r
+       while (true)\r
+       {\r
+               SOCK *new_sock = Accept(s);\r
+\r
+               if (new_sock == NULL)\r
+               {\r
+                       break;\r
+               }\r
+               else\r
+               {\r
+                       CHECK_NETWORK_2 c;\r
+                       THREAD *t;\r
+\r
+                       Zero(&c, sizeof(c));\r
+                       c.s = new_sock;\r
+                       c.k = pri;\r
+                       c.x = x;\r
+\r
+                       t = NewThread(CheckNetworkAcceptThread, &c);\r
+                       Insert(o, t);\r
+               }\r
+       }\r
+\r
+       for (i = 0;i < LIST_NUM(o);i++)\r
+       {\r
+               THREAD *t = LIST_DATA(o, i);\r
+               WaitThread(t, INFINITE);\r
+               ReleaseThread(t);\r
+       }\r
+\r
+       FreeK(pri);\r
+       FreeK(pub);\r
+\r
+       FreeX(x);\r
+\r
+       ReleaseSock(s);\r
+       ReleaseList(o);\r
+}\r
+\r
+// ネットワーク機能チェック\r
+bool CheckNetwork()\r
+{\r
+       CHECK_NETWORK_1 c;\r
+       THREAD *t;\r
+       SOCK *listen_socket;\r
+       UINT port;\r
+       UINT i, num;\r
+       bool ok = true;\r
+       SOCK **socks;\r
+       SOCK_EVENT *se = NewSockEvent();\r
+\r
+       Zero(&c, sizeof(c));\r
+       t = NewThread(CheckNetworkListenThread, &c);\r
+       WaitThreadInit(t);\r
+\r
+       listen_socket = c.ListenSocket;\r
+\r
+       port = listen_socket->LocalPort;\r
+\r
+       num = 8;\r
+       socks = ZeroMalloc(sizeof(SOCK *) * num);\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               socks[i] = Connect("localhost", port);\r
+               if (socks[i] == NULL)\r
+               {\r
+                       Print("Connect Failed. (%u)\n", i);\r
+                       ok = false;\r
+                       num = i;\r
+                       break;\r
+               }\r
+               if (StartSSL(socks[i], NULL, NULL) == false)\r
+               {\r
+                       ReleaseSock(socks[i]);\r
+                       Print("Connect Failed. (%u)\n", i);\r
+                       ok = false;\r
+                       num = i;\r
+                       break;\r
+               }\r
+\r
+               JoinSockToSockEvent(socks[i], se);\r
+       }\r
+\r
+       if (ok)\r
+       {\r
+               while (true)\r
+               {\r
+                       UINT i;\r
+                       bool end = false;\r
+                       bool all_blocked = true;\r
+\r
+                       for (i = 0;i < num;i++)\r
+                       {\r
+                               UINT n;\r
+                               UINT ret;\r
+\r
+                               n = 0;\r
+                               ret = Recv(socks[i], &n, sizeof(UINT), true);\r
+                               if (ret == 0)\r
+                               {\r
+                                       Print("Recv Failed (Disconnected).\n", ret);\r
+                                       end = true;\r
+                                       ok = false;\r
+                               }\r
+                               if (ret != SOCK_LATER)\r
+                               {\r
+                                       all_blocked = false;\r
+                               }\r
+\r
+                               if (n >= 128)\r
+                               {\r
+                                       end = true;\r
+                               }\r
+                       }\r
+\r
+                       if (end)\r
+                       {\r
+                               break;\r
+                       }\r
+\r
+                       if (all_blocked)\r
+                       {\r
+                               WaitSockEvent(se, INFINITE);\r
+                       }\r
+               }\r
+       }\r
+\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               Disconnect(socks[i]);\r
+               ReleaseSock(socks[i]);\r
+       }\r
+       Free(socks);\r
+\r
+       Disconnect(listen_socket);\r
+\r
+       WaitThread(t, INFINITE);\r
+       ReleaseThread(t);\r
+\r
+       ReleaseSock(listen_socket);\r
+\r
+       ReleaseSockEvent(se);\r
+\r
+       return ok;\r
+}\r
+\r
+typedef struct CHECK_THREAD_1\r
+{\r
+       UINT num;\r
+       LOCK *lock;\r
+       THREAD *wait_thread;\r
+} CHECK_THREAD_1;\r
+\r
+static UINT check_thread_global_1 = 0;\r
+\r
+#define        CHECK_THREAD_INCREMENT_COUNT            32\r
+\r
+// テストスレッド 1\r
+void CheckThread1(THREAD *thread, void *param)\r
+{\r
+       CHECK_THREAD_1 *ct1 = (CHECK_THREAD_1 *)param;\r
+       UINT i;\r
+       UINT num = CHECK_THREAD_INCREMENT_COUNT;\r
+\r
+       WaitThread(ct1->wait_thread, INFINITE);\r
+\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               Lock(ct1->lock);\r
+               check_thread_global_1 = ct1->num;\r
+               InputToNull((void *)check_thread_global_1);\r
+               check_thread_global_1 = check_thread_global_1 + 1 + RetZero();\r
+               ct1->num = check_thread_global_1;\r
+               Unlock(ct1->lock);\r
+       }\r
+}\r
+\r
+// テストスレッド 2\r
+void CheckThread2(THREAD *thread, void *param)\r
+{\r
+       EVENT *e = (EVENT *)param;\r
+       Wait(e, INFINITE);\r
+}\r
+\r
+typedef struct CHECK_THREAD_3\r
+{\r
+       UINT num, a;\r
+} CHECK_THREAD_3;\r
+\r
+// テストスレッド 3\r
+void CheckThread3(THREAD *thread, void *param)\r
+{\r
+       CHECK_THREAD_3 *c = (CHECK_THREAD_3 *)param;\r
+       THREAD *t;\r
+\r
+       if (c->num == 0)\r
+       {\r
+               return;\r
+       }\r
+       c->num--;\r
+       c->a++;\r
+\r
+       t = NewThread(CheckThread3, c);\r
+       WaitThread(t, INFINITE);\r
+       ReleaseThread(t);\r
+}\r
+\r
+// スレッドチェック\r
+bool CheckThread()\r
+{\r
+       bool ok = true;\r
+       CHECK_THREAD_1 ct1;\r
+       UINT num = 32;\r
+       UINT i;\r
+       THREAD **threads;\r
+       EVENT *e;\r
+       THREAD *t2;\r
+       THREAD *t;\r
+       CHECK_THREAD_3 c;\r
+\r
+       e = NewEvent();\r
+\r
+       Zero(&ct1, sizeof(ct1));\r
+       ct1.lock = NewLock();\r
+\r
+       t2 = NewThread(CheckThread2, e);\r
+       ct1.wait_thread = t2;\r
+\r
+       threads = ZeroMalloc(sizeof(THREAD *) * num);\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               threads[i] = NewThread(CheckThread1, &ct1);\r
+               if (threads[i] == NULL)\r
+               {\r
+                       Print("Thread %u Create Failed.\n", i);\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       Set(e);\r
+\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               WaitThread(threads[i], INFINITE);\r
+               ReleaseThread(threads[i]);\r
+       }\r
+\r
+       Free(threads);\r
+\r
+       if (ct1.num != (num * CHECK_THREAD_INCREMENT_COUNT))\r
+       {\r
+               Print("Threading: %u != %u\n", ct1.num, num * CHECK_THREAD_INCREMENT_COUNT);\r
+               ok = false;\r
+       }\r
+\r
+       DeleteLock(ct1.lock);\r
+\r
+       WaitThread(t2, INFINITE);\r
+       ReleaseThread(t2);\r
+\r
+       ReleaseEvent(e);\r
+\r
+       num = 32;\r
+\r
+       Zero(&c, sizeof(c));\r
+       c.num = num;\r
+       t = NewThread(CheckThread3, &c);\r
+       WaitThread(t, INFINITE);\r
+       ReleaseThread(t);\r
+\r
+       if (c.a != num)\r
+       {\r
+               Print("Threading: %u != %u\n", c.a, num);\r
+               ok = false;\r
+       }\r
+\r
+       return ok;\r
+}\r
+\r
+// ファイルシステムチェック\r
+bool CheckFileSystem()\r
+{\r
+       bool ok = true;\r
+       char exe[MAX_PATH];\r
+       char exe_dir[MAX_PATH];\r
+       DIRLIST *dirs;\r
+       UINT i;\r
+\r
+       GetExeName(exe, sizeof(exe));\r
+       GetExeDir(exe_dir, sizeof(exe_dir));\r
+\r
+       ok = false;\r
+       dirs = EnumDir(exe_dir);\r
+       for (i = 0;i < dirs->NumFiles;i++)\r
+       {\r
+               if (EndWith(exe, dirs->File[i]->FileName))\r
+               {\r
+                       ok = true;\r
+                       break;\r
+               }\r
+       }\r
+       FreeDir(dirs);\r
+\r
+       if (ok == false)\r
+       {\r
+               Print("EnumDir Failed.\n");\r
+               return false;\r
+       }\r
+       else\r
+       {\r
+               UINT size = 1234567;\r
+               UCHAR *buf;\r
+               IO *io;\r
+#ifndef        OS_WIN32\r
+               wchar_t *filename = L"/tmp/vpn_checker_tmp";\r
+#else  // OS_WIN32\r
+               wchar_t filename[MAX_PATH];\r
+               CombinePathW(filename, sizeof(filename), MsGetMyTempDirW(), L"vpn_checker_tmp");\r
+#endif // OS_WIN32\r
+\r
+               buf = Malloc(size);\r
+               for (i = 0;i < size;i++)\r
+               {\r
+                       buf[i] = i % 256;\r
+               }\r
+\r
+               io = FileCreateW(filename);\r
+               if (io == NULL)\r
+               {\r
+                       Print("FileCreate Failed.\n");\r
+                       Free(buf);\r
+                       return false;\r
+               }\r
+               else\r
+               {\r
+                       FileWrite(io, buf, size);\r
+                       Free(buf);\r
+                       FileClose(io);\r
+\r
+                       io = FileOpenW(filename, false);\r
+                       if (FileSize(io) != 1234567)\r
+                       {\r
+                               Print("FileSize Failed.\n");\r
+                               FileClose(io);\r
+                               return false;\r
+                       }\r
+                       else\r
+                       {\r
+                               BUF *b;\r
+\r
+                               FileClose(io);\r
+                               b = ReadDumpW(filename);\r
+\r
+                               for (i = 0;i < b->Size;i++)\r
+                               {\r
+                                       UCHAR c = ((UCHAR *)b->Buf)[i];\r
+\r
+                                       if (c != (i % 256))\r
+                                       {\r
+                                               Print("FileToBuf Failed.\n");\r
+                                               FreeBuf(b);\r
+                                               return false;\r
+                                       }\r
+                               }\r
+\r
+                               FreeBuf(b);\r
+                       }\r
+               }\r
+\r
+               FileDeleteW(filename);\r
+       }\r
+\r
+       return ok;\r
+}\r
+\r
+// 文字列チェック\r
+bool CheckStrings()\r
+{\r
+       wchar_t *numstr = _UU("CHECK_TEST_123456789");\r
+       char tmp[MAX_SIZE];\r
+       wchar_t tmp2[MAX_SIZE];\r
+       UINT i;\r
+       UINT sum, sum2;\r
+       UNI_TOKEN_LIST *t;\r
+\r
+       UniStrCpy(tmp2, sizeof(tmp2), L"");\r
+\r
+       sum2 = 0;\r
+       for (i = 0;i < 64;i++)\r
+       {\r
+               sum2 += i;\r
+               UniFormat(tmp2, sizeof(tmp2), L"%s,%u", tmp2, i);\r
+       }\r
+\r
+       t = UniParseToken(tmp2, L",");\r
+\r
+       sum = 0;\r
+\r
+       for (i = 0;i < t->NumTokens;i++)\r
+       {\r
+               wchar_t *s = t->Token[i];\r
+               UINT n = UniToInt(s);\r
+\r
+               sum += n;\r
+       }\r
+\r
+       UniFreeToken(t);\r
+\r
+       if (sum != sum2)\r
+       {\r
+               Print("UniParseToken Failed.\n");\r
+               return false;\r
+       }\r
+\r
+       if (UniToInt(numstr) != 123456789)\r
+       {\r
+               Print("UniToInt Failed.\n");\r
+               return false;\r
+       }\r
+\r
+       UniToStr(tmp, sizeof(tmp), numstr);\r
+       if (ToInt(tmp) != 123456789)\r
+       {\r
+               Print("UniToStr Failed.\n");\r
+               return false;\r
+       }\r
+\r
+       StrToUni(tmp2, sizeof(tmp2), _SS("CHECK_TEST_TESTSTR"));\r
+       if (UniStrCmp(_UU("CHECK_TEST_TESTSTR"), tmp2) != 0)\r
+       {\r
+               Print("StrToUni Failed.\n");\r
+               printf("[%S] [%S]\n", tmp2, _UU("CHECK_TEST_TESTSTR"));\r
+               return false;\r
+       }\r
+\r
+       ReplaceStrEx(tmp, sizeof(tmp), _SS("CHECK_TEST_REPLACE1"), _SS("CHECK_TEST_REPLACE3"),\r
+               _SS("CHECK_TEST_REPLACE4"), false);\r
+\r
+       if (StrCmp(tmp, _SS("CHECK_TEST_REPLACE2")) != 0)\r
+       {\r
+               Print("ReplaceStrEx Failed.\n");\r
+               return false;\r
+       }\r
+\r
+       UniReplaceStrEx(tmp2, sizeof(tmp2), _UU("CHECK_TEST_REPLACE1"), _UU("CHECK_TEST_REPLACE3"),\r
+               _UU("CHECK_TEST_REPLACE4"), false);\r
+\r
+       if (UniStrCmp(tmp2, _UU("CHECK_TEST_REPLACE2")) != 0)\r
+       {\r
+               Print("UniReplaceStrEx Failed.\n");\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// メモリチェック\r
+bool CheckMemory()\r
+{\r
+       UINT i, num, size, j;\r
+       void **pp;\r
+       bool ok = true;\r
+       UINT old_size;\r
+\r
+       num = 2000;\r
+       size = 1000;\r
+       pp = ZeroMalloc(sizeof(void *) * num);\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               pp[i] = ZeroMalloc(size);\r
+               InputToNull(pp[i]);\r
+               for (j = 0;j < size;j++)\r
+               {\r
+                       ((UCHAR *)pp[i])[j] = j % 256;\r
+               }\r
+       }\r
+       old_size = size;\r
+       size = size * 3;\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               pp[i] = ReAlloc(pp[i], size);\r
+               for (j = old_size;j < size;j++)\r
+               {\r
+                       InputToNull((void *)(UINT)(((UCHAR *)pp[i])[j] = j % 256));\r
+               }\r
+       }\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               for (j = 0;j < size;j++)\r
+               {\r
+                       if (((UCHAR *)pp[i])[j] != (j % 256))\r
+                       {\r
+                               ok = false;\r
+                       }\r
+               }\r
+               Free(pp[i]);\r
+       }\r
+       Free(pp);\r
+\r
+       return ok;\r
+}\r
+\r
+// 何もしない関数\r
+void InputToNull(void *p)\r
+{\r
+       // 意味不明!\r
+       if (RetZero() == 1)\r
+       {\r
+               UCHAR *c = (UCHAR *)p;\r
+               c[0] = 0x32;\r
+       }\r
+}\r
+\r
+// 0 を返す関数\r
+UINT RetZero()\r
+{\r
+       // 意味不明!\r
+       if (g_debug == 0x123455)\r
+       {\r
+               return 1;\r
+       }\r
+       else\r
+       {\r
+               return 0;\r
+       }\r
+}\r
+\r
+\r
+// カーネルチェック\r
+bool CheckKernel()\r
+{\r
+       UINT num = 10, i;\r
+       UINT64 s = Tick64();\r
+       UINT64 t = Tick64();\r
+\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               UINT64 q = Tick64();\r
+               if (t > q)\r
+               {\r
+                       Print("Tick64 #1 Failed.\n");\r
+                       return false;\r
+               }\r
+\r
+               t = q;\r
+\r
+               SleepThread(100);\r
+       }\r
+\r
+       t = (Tick64() - s);\r
+       if (t <= 500 || t >= 2000)\r
+       {\r
+               Print("Tick64 #2 Failed.\n");\r
+               return false;\r
+       }\r
+       else if (false)\r
+       {\r
+               UINT64 tick1 = Tick64();\r
+               UINT64 time1;\r
+               UINT64 tick2, time2;\r
+\r
+               SleepThread(1000);\r
+\r
+               tick2 = Tick64();\r
+               time2 = LocalTime64();\r
+               time1 = SystemToLocal64(TickToTime(tick1));\r
+\r
+               if (time2 > time1)\r
+               {\r
+                       s = time2 - time1;\r
+               }\r
+               else\r
+               {\r
+                       s = time1 - time2;\r
+               }\r
+\r
+               if (s <= 500 || s >= 2000)\r
+               {\r
+                       Print("TickToTime Failed.\n");\r
+                       return false;\r
+               }\r
+       }\r
+\r
+#ifdef OS_UNIX\r
+       {\r
+               // 子プロセスのテスト\r
+               UINT pid;\r
+               char exe[MAX_SIZE];\r
+\r
+               GetExeName(exe, sizeof(exe));\r
+\r
+               pid = fork();\r
+\r
+               if (pid == -1)\r
+               {\r
+                       Print("fork Failed.\n");\r
+                       return false;\r
+               }\r
+\r
+               if (pid == 0)\r
+               {\r
+                       char *param = UNIX_ARG_EXIT;\r
+                       char **args;\r
+\r
+                       args = ZeroMalloc(sizeof(char *) * 3);\r
+                       args[0] = exe;\r
+                       args[1] = param;\r
+                       args[2] = NULL;\r
+\r
+                       setsid();\r
+\r
+                       // 標準入出力をクローズする\r
+                       UnixCloseIO();\r
+\r
+                       // 不要なシグナルを停止する\r
+                       signal(SIGHUP, SIG_IGN);\r
+\r
+                       execvp(exe, args);\r
+                       AbortExit();\r
+               }\r
+               else\r
+               {\r
+                       int status = 0, ret;\r
+\r
+                       // 子プロセスの終了を待機する\r
+                       ret = waitpid(pid, &status, 0);\r
+\r
+                       if (WIFEXITED(status) == 0)\r
+                       {\r
+                               // 異常終了した\r
+                               Print("waitpid Failed: 0x%x\n", ret);\r
+                               return false;\r
+                       }\r
+               }\r
+       }\r
+#endif // OS_UNIX\r
+\r
+       return true;\r
+}\r
+\r
+// システムチェッカ\r
+bool SystemCheck()\r
+{\r
+       UINT i;\r
+       bool ng = false;\r
+\r
+       UniPrint(_UU("CHECK_TITLE"));\r
+       UniPrint(_UU("CHECK_NOTE"));\r
+       for (i = 0;i < sizeof(checker_procs) / sizeof(checker_procs[0]);i++)\r
+       {\r
+               wchar_t *title;\r
+               bool ret = false;\r
+               CHECKER_PROC *p = &checker_procs[i];\r
+\r
+               title = _UU(p->Title);\r
+\r
+               UniPrint(_UU("CHECK_EXEC_TAG"), title);\r
+\r
+               ret = p->Proc();\r
+\r
+               if (ret == false)\r
+               {\r
+                       ng = true;\r
+               }\r
+\r
+               UniPrint(L"              %s\n", ret ? _UU("CHECK_PASS") : _UU("CHECK_FAIL"));\r
+       }\r
+\r
+       UniPrint(L"\n");\r
+       if (ng == false)\r
+       {\r
+               UniPrint(L"%s\n\n", _UU("CHECK_RESULT_1"));\r
+       }\r
+       else\r
+       {\r
+               UniPrint(L"%s\n\n", _UU("CHECK_RESULT_2"));\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+\r
+// 動作チェッカ\r
+UINT PtCheck(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       UINT ret = ERR_NO_ERROR;\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (SystemCheck() == false)\r
+       {\r
+               ret = ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// VPN Tools メイン関数\r
+void PtMain(PT *pt)\r
+{\r
+       char prompt[MAX_SIZE];\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (pt == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 起動が完了したメッセージを表示する\r
+       UniFormat(tmp, sizeof(tmp), _UU("CMD_UTVPNCMD_TOOLS_CONNECTED"));\r
+       pt->Console->Write(pt->Console, tmp);\r
+       pt->Console->Write(pt->Console, L"");\r
+\r
+       while (true)\r
+       {\r
+               // コマンドの定義\r
+               CMD cmd[] =\r
+               {\r
+                       {"About", PsAbout},\r
+                       {"MakeCert", PtMakeCert},\r
+                       {"TrafficClient", PtTrafficClient},\r
+                       {"TrafficServer", PtTrafficServer},\r
+                       {"Check", PtCheck},\r
+               };\r
+\r
+               // プロンプトの生成\r
+               StrCpy(prompt, sizeof(prompt), "VPN Tools>");\r
+\r
+               if (DispatchNextCmdEx(pt->Console, pt->CmdLine, prompt, cmd, sizeof(cmd) / sizeof(cmd[0]), pt) == false)\r
+               {\r
+                       break;\r
+               }\r
+               pt->LastError = pt->Console->RetCode;\r
+\r
+               if (pt->LastError == ERR_NO_ERROR && pt->Console->ConsoleType != CONSOLE_CSV)\r
+               {\r
+                       pt->Console->Write(pt->Console, _UU("CMD_MSG_OK"));\r
+                       pt->Console->Write(pt->Console, L"");\r
+               }\r
+\r
+               if (pt->CmdLine != NULL)\r
+               {\r
+                       break;\r
+               }\r
+       }\r
+}\r
+\r
+// VPN Tools コンテキストの作成\r
+PT *NewPt(CONSOLE *c, wchar_t *cmdline)\r
+{\r
+       PT *pt;\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       if (UniIsEmptyStr(cmdline))\r
+       {\r
+               cmdline = NULL;\r
+       }\r
+\r
+       pt = ZeroMalloc(sizeof(PT));\r
+       pt->Console = c;\r
+       pt->CmdLine = CopyUniStr(cmdline);\r
+\r
+       return pt;\r
+}\r
+\r
+// VPN Tools コンテキストの解放\r
+void FreePt(PT *pt)\r
+{\r
+       // 引数チェック\r
+       if (pt == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(pt->CmdLine);\r
+       Free(pt);\r
+}\r
+\r
+// VPN Tools 開始\r
+UINT PtConnect(CONSOLE *c, wchar_t *cmdline)\r
+{\r
+       PT *pt;\r
+       UINT ret = 0;\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       pt = NewPt(c, cmdline);\r
+\r
+       PtMain(pt);\r
+\r
+       ret = pt->LastError;\r
+\r
+       FreePt(pt);\r
+\r
+       return ret;\r
+}\r
+\r
+// vpncmd コマンドの起動パス情報の初期化\r
+void VpnCmdInitBootPath()\r
+{\r
+#ifdef OS_WIN32\r
+       char exe_path[MAX_PATH];\r
+       char tmp[MAX_PATH];\r
+       GetExeName(exe_path, sizeof(exe_path));\r
+\r
+       if (SearchStrEx(exe_path, "ham.exe", 0, false) != INFINITE || SearchStrEx(exe_path, "ham_x64.exe", 0, false) != INFINITE || SearchStrEx(exe_path, "ham_ia64.exe", 0, false) != INFINITE)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (MsIsAdmin())\r
+       {\r
+               UINT current_ver;\r
+\r
+               // 現在インストールされている vpncmd のバージョンの取得\r
+               current_ver = MsRegReadInt(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_VER);\r
+\r
+               if ((CEDAR_BUILD >= current_ver) ||\r
+                       MsRegIsValue(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH) == false)\r
+               {\r
+                       char *src_filename;\r
+                       bool b = false;\r
+                       // vpncmdsys.exe を system32 にコピーする\r
+                       if (MsIsNt())\r
+                       {\r
+                               Format(tmp, sizeof(tmp), "%s\\utvpncmd.exe", MsGetSystem32Dir());\r
+                       }\r
+                       else\r
+                       {\r
+                               Format(tmp, sizeof(tmp), "%s\\utvpncmd.exe", MsGetWindowsDir());\r
+                       }\r
+\r
+                       src_filename = VPNCMD_BOOTSTRAP_FILENAME;\r
+\r
+                       if (IsX64())\r
+                       {\r
+                               src_filename = VPNCMD_BOOTSTRAP_FILENAME_X64;\r
+                       }\r
+\r
+                       if (IsIA64())\r
+                       {\r
+                               src_filename = VPNCMD_BOOTSTRAP_FILENAME_IA64;\r
+                       }\r
+\r
+                       b = true;\r
+\r
+                       if (MsIs64BitWindows() == false || Is64())\r
+                       {\r
+                               if (IsFile(tmp) == false || (CEDAR_BUILD > current_ver) || MsRegIsValue(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH) == false)\r
+                               {\r
+                                       b = FileCopy(src_filename, tmp);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               void *wow;\r
+\r
+                               wow = MsDisableWow64FileSystemRedirection();\r
+\r
+                               if (true)\r
+                               {\r
+                                       if (IsFile(tmp) == false || (CEDAR_BUILD > current_ver) || MsRegIsValue(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH) == false)\r
+                                       {\r
+                                               b = FileCopy(src_filename, tmp);\r
+                                       }\r
+                               }\r
+\r
+                               MsRestoreWow64FileSystemRedirection(wow);\r
+\r
+                               if (true)\r
+                               {\r
+                                       if (IsFile(tmp) == false || (CEDAR_BUILD > current_ver) || MsRegIsValue(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH) == false)\r
+                                       {\r
+                                               b = FileCopy(src_filename, tmp);\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       // 現在実行しているプロンプトのほうがバージョンが新しいのでレジストリを上書きする\r
+                       if (MsIs64BitWindows() == false)\r
+                       {\r
+                               MsRegWriteStr(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH, exe_path);\r
+                               MsRegWriteInt(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_VER, CEDAR_BUILD);\r
+                       }\r
+                       else\r
+                       {\r
+                               MsRegWriteStrEx2(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH, exe_path, true, false);\r
+                               MsRegWriteIntEx2(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_VER, CEDAR_BUILD, true, false);\r
+\r
+                               MsRegWriteStrEx2(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_PATH, exe_path, false, true);\r
+                               MsRegWriteIntEx2(REG_LOCAL_MACHINE, VPNCMD_BOOTSTRAP_REG_KEYNAME, VPNCMD_BOOTSTRAP_REG_VALUENAME_VER, CEDAR_BUILD, false, true);\r
+                       }\r
+               }\r
+       }\r
+#endif // OS_WIN32\r
+}\r
+\r
+// 文字列の表示\r
+void TtPrint(void *param, TT_PRINT_PROC *print_proc, wchar_t *str)\r
+{\r
+       // 引数チェック\r
+       if (print_proc == NULL || str == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       print_proc(param, str);\r
+}\r
+\r
+// 新しいランダムデータの生成\r
+void TtGenerateRandomData(UCHAR **buf, UINT *size)\r
+{\r
+       UCHAR *tmp;\r
+       UINT sz;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (buf == NULL || size == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       sz = TRAFFIC_BUF_SIZE;\r
+       tmp = Malloc(sz);\r
+       for (i = 0;i < sz;i++)\r
+       {\r
+               tmp[i] = rand() % 256;\r
+\r
+               if (tmp[i] == '!')\r
+               {\r
+                       tmp[i] = '_';\r
+               }\r
+       }\r
+\r
+       *buf = tmp;\r
+       *size = sz;\r
+}\r
+\r
+// 通信スループット測定サーバーワーカースレッド\r
+void TtsWorkerThread(THREAD *thread, void *param)\r
+{\r
+       TTS *tts;\r
+       UINT buf_size;\r
+       UCHAR *send_buf_data, *recv_buf_data;\r
+       bool all_sockets_blocked = false;\r
+       UINT64 tmp64;\r
+       LIST *o;\r
+       UINT i;\r
+       wchar_t tmp[MAX_SIZE];\r
+       bool dont_block_next_time = false;\r
+       char *ver_str = TRAFFIC_VER_STR;\r
+       // 引数チェック\r
+       if (thread == NULL || param == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // データ領域の確保\r
+       TtGenerateRandomData(&send_buf_data, &buf_size);\r
+       TtGenerateRandomData(&recv_buf_data, &buf_size);\r
+\r
+       tts = (TTS *)param;\r
+\r
+       // ソケットイベントの準備\r
+       tts->SockEvent = NewSockEvent();\r
+       AddRef(tts->SockEvent->ref);\r
+\r
+       // サーバーソケットリストの準備\r
+       tts->TtsSockList = NewList(NULL);\r
+\r
+       // 親スレッドに準備完了を伝える\r
+       NoticeThreadInit(thread);\r
+\r
+       o = NewList(NULL);\r
+\r
+       while (tts->Halt == false)\r
+       {\r
+               // すべてのソケットを待機する\r
+               if (dont_block_next_time == false)\r
+               {\r
+                       WaitSockEvent(tts->SockEvent, 50);\r
+               }\r
+               dont_block_next_time = false;\r
+\r
+               // 現在登録されているソケットについて処理する\r
+               LockList(tts->TtsSockList);\r
+               {\r
+                       UINT i;\r
+\r
+                       all_sockets_blocked = false;\r
+\r
+                       // すべてのソケットがブロック状態にならない限り\r
+                       // データの送受信を続ける\r
+                       while (all_sockets_blocked == false)\r
+                       {\r
+                               all_sockets_blocked = true;\r
+\r
+                               for (i = 0;i < LIST_NUM(tts->TtsSockList);i++)\r
+                               {\r
+                                       UINT ret = SOCK_LATER;\r
+                                       UCHAR *send_data = NULL, *recv_data = NULL;\r
+                                       UINT send_size = 0, recv_size = 0;\r
+                                       TTS_SOCK *ts = LIST_DATA(tts->TtsSockList, i);\r
+                                       bool blocked_for_this_socket = false;\r
+\r
+                                       if (ts->SockJoined == false)\r
+                                       {\r
+                                               JoinSockToSockEvent(ts->Sock, tts->SockEvent);\r
+                                               ts->SockJoined = true;\r
+                                       }\r
+\r
+                                       switch (ts->State)\r
+                                       {\r
+                                       case 0:\r
+                                               // バージョン文字列を返す\r
+                                               ret = Send(ts->Sock, ver_str, TRAFFIC_VER_STR_SIZE, false);\r
+                                               if (ret != 0 && ret != SOCK_LATER)\r
+                                               {\r
+                                                       ts->State = 5;\r
+                                               }\r
+                                               break;\r
+\r
+                                       case 5:\r
+                                               // クライアントから方向を受信する\r
+                                               ret = Recv(ts->Sock, recv_buf_data, buf_size, false);\r
+                                               if (ret != 0 && ret != SOCK_LATER)\r
+                                               {\r
+                                                       UCHAR c;\r
+\r
+                                                       // 受信した 1 バイト目にデータの方向が入っている\r
+                                                       c = recv_buf_data[0];\r
+\r
+                                                       if (c == 0)\r
+                                                       {\r
+                                                               // 0 の場合はクライアント -> サーバー\r
+                                                               ts->State = 1;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               // それ以外の場合はサーバー -> クライアント\r
+                                                               ts->State = 2;\r
+                                                       }\r
+                                               }\r
+                                               break;\r
+\r
+                                       case 1:\r
+                                               // クライアント -> サーバー\r
+                                               ret = Recv(ts->Sock, recv_buf_data, buf_size, false);\r
+\r
+                                               if (ret != 0 && ret != SOCK_LATER)\r
+                                               {\r
+                                                       // 受信した 1 バイト目を検査する\r
+                                                       UCHAR c = recv_buf_data[0];\r
+\r
+                                                       if (c == '!')\r
+                                                       {\r
+                                                               // サーバーからクライアントにサイズ情報を通知\r
+                                                               ts->State = 3;\r
+                                                               Debug("!");\r
+                                                       }\r
+                                               }\r
+                                               break;\r
+\r
+                                       case 2:\r
+                                               // サーバー -> クライアント\r
+                                               ret = Send(ts->Sock, send_buf_data, buf_size, false);\r
+                                               break;\r
+\r
+                                       case 3:\r
+                                               // サーバー -> クライアントにサイズ情報を通知する\r
+                                               tmp64 = Endian64(ts->NumBytes);\r
+\r
+                                               Recv(ts->Sock, recv_buf_data, buf_size, false);\r
+\r
+                                               if (ts->LastWaitTick == 0 || ts->LastWaitTick <= Tick64())\r
+                                               {\r
+                                                       ret = Send(ts->Sock, &tmp64, sizeof(tmp64), false);\r
+\r
+                                                       if (ret != SOCK_LATER)\r
+                                                       {\r
+                                                               ts->LastWaitTick = Tick64() + 100;\r
+                                                       }\r
+                                               }\r
+                                               break;\r
+                                       }\r
+\r
+                                       if (ret == 0)\r
+                                       {\r
+                                               // 切断されたのでこのソケットを削除としてマークする\r
+                                               Insert(o, ts);\r
+                                       }\r
+                                       else if (ret == SOCK_LATER)\r
+                                       {\r
+                                               // 遅延が発生した\r
+                                               blocked_for_this_socket = true;\r
+                                               dont_block_next_time = false;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               if (ts->State == 1)\r
+                                               {\r
+                                                       ts->NumBytes += (UINT64)ret;\r
+                                               }\r
+                                       }\r
+\r
+                                       if (blocked_for_this_socket == false)\r
+                                       {\r
+                                               all_sockets_blocked = false;\r
+                                       }\r
+                               }\r
+\r
+                               if (LIST_NUM(o) != 0)\r
+                               {\r
+                                       UINT i;\r
+                                       // 1 つ以上のソケットが切断された\r
+                                       for (i = 0;i < LIST_NUM(o);i++)\r
+                                       {\r
+                                               TTS_SOCK *ts = LIST_DATA(o, i);\r
+\r
+                                               UniFormat(tmp, sizeof(tmp), _UU("TTS_DISCONNECTED"), ts->Id, ts->Sock->RemoteHostname);\r
+                                               TtPrint(tts->Param, tts->Print, tmp);\r
+\r
+                                               Disconnect(ts->Sock);\r
+                                               ReleaseSock(ts->Sock);\r
+\r
+                                               Delete(tts->TtsSockList, ts);\r
+\r
+                                               Free(ts);\r
+                                       }\r
+\r
+                                       DeleteAll(o);\r
+                               }\r
+\r
+                               if (tts->NewSocketArrived || tts->Halt)\r
+                               {\r
+                                       tts->NewSocketArrived = false;\r
+                                       all_sockets_blocked = true;\r
+                                       dont_block_next_time = true;\r
+                               }\r
+                       }\r
+               }\r
+               UnlockList(tts->TtsSockList);\r
+       }\r
+\r
+       LockList(tts->TtsSockList);\r
+       {\r
+               // 残留しているすべてのソケットを解放する\r
+               for (i = 0;i < LIST_NUM(tts->TtsSockList);i++)\r
+               {\r
+                       TTS_SOCK *ts = LIST_DATA(tts->TtsSockList, i);\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("TTS_DISCONNECT"), ts->Id, ts->Sock->RemoteHostname);\r
+                       TtPrint(tts->Param, tts->Print, tmp);\r
+\r
+                       Disconnect(ts->Sock);\r
+                       ReleaseSock(ts->Sock);\r
+\r
+                       Free(ts);\r
+               }\r
+       }\r
+       UnlockList(tts->TtsSockList);\r
+\r
+       // クリーンアップ\r
+       ReleaseList(o);\r
+       ReleaseList(tts->TtsSockList);\r
+       ReleaseSockEvent(tts->SockEvent);\r
+       Free(send_buf_data);\r
+       Free(recv_buf_data);\r
+}\r
+\r
+// IPv6 用 Accept スレッド\r
+void TtsIPv6AcceptThread(THREAD *thread, void *param)\r
+{\r
+       TTS *tts = (TTS *)param;\r
+       // 引数チェック\r
+       if (tts == NULL || param == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       TtsAcceptProc(tts, tts->ListenSocketV6);\r
+}\r
+\r
+// Accept プロシージャ\r
+void TtsAcceptProc(TTS *tts, SOCK *listen_socket)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (tts == NULL || listen_socket == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       while (tts->Halt == false)\r
+       {\r
+               SOCK *s;\r
+               // Accept する\r
+               s = Accept(listen_socket);\r
+\r
+               if (s == NULL)\r
+               {\r
+                       if (tts->Halt == false)\r
+                       {\r
+                               SleepThread(10);\r
+                       }\r
+                       continue;\r
+               }\r
+               else\r
+               {\r
+                       // クライアントから接続された\r
+                       AcceptInit(s);\r
+                       tts->NewSocketArrived = true;\r
+                       LockList(tts->TtsSockList);\r
+                       {\r
+                               TTS_SOCK *ts = ZeroMalloc(sizeof(TTS_SOCK));\r
+\r
+                               ts->Id = (++tts->IdSeed);\r
+                               ts->Sock = s;\r
+\r
+                               UniFormat(tmp, sizeof(tmp), _UU("TTS_ACCEPTED"), ts->Id,\r
+                                       s->RemoteHostname, s->RemotePort);\r
+                               TtPrint(tts->Param, tts->Print, tmp);\r
+\r
+                               Insert(tts->TtsSockList, ts);\r
+                               tts->NewSocketArrived = true;\r
+                       }\r
+                       UnlockList(tts->TtsSockList);\r
+               }\r
+       }\r
+}\r
+\r
+// 通信スループット測定サーバー待機スレッド\r
+void TtsListenThread(THREAD *thread, void *param)\r
+{\r
+       TTS *tts;\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (thread == NULL || param == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       tts = (TTS *)param;\r
+\r
+       tts->ListenSocket = NULL;\r
+       tts->ListenSocket = Listen(tts->Port);\r
+       tts->ListenSocketV6 = Listen6(tts->Port);\r
+\r
+       if (tts->ListenSocket == NULL && tts->ListenSocketV6 == NULL)\r
+       {\r
+               // Listen に失敗した\r
+               UniFormat(tmp, sizeof(tmp), _UU("TT_LISTEN_FAILED"), tts->Port);\r
+               TtPrint(tts->Param, tts->Print, tmp);\r
+\r
+               // 親スレッドに準備完了を伝える\r
+               NoticeThreadInit(thread);\r
+\r
+               tts->ErrorCode = ERR_INTERNAL_ERROR;\r
+       }\r
+       else\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), _UU("TTS_LISTEN_STARTED"), tts->Port);\r
+               TtPrint(tts->Param, tts->Print, tmp);\r
+\r
+               if (tts->ListenSocketV6 != NULL)\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("TTS_LISTEN_STARTED_V6"), tts->Port);\r
+                       TtPrint(tts->Param, tts->Print, tmp);\r
+               }\r
+               else\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("TTS_LISTEN_FAILED_V6"), tts->Port);\r
+                       TtPrint(tts->Param, tts->Print, tmp);\r
+               }\r
+\r
+               if (tts->ListenSocket != NULL)\r
+               {\r
+                       AddRef(tts->ListenSocket->ref);\r
+               }\r
+               if (tts->ListenSocketV6 != NULL)\r
+               {\r
+                       AddRef(tts->ListenSocketV6->ref);\r
+               }\r
+\r
+               // ワーカースレッドを開始する\r
+               tts->WorkThread = NewThread(TtsWorkerThread, tts);\r
+               WaitThreadInit(tts->WorkThread);\r
+\r
+               // 親スレッドに準備完了を伝える\r
+               NoticeThreadInit(thread);\r
+\r
+               // IPv6 用 Accept スレッドを準備\r
+               tts->IPv6AcceptThread = NULL;\r
+               if (tts->ListenSocketV6 != NULL)\r
+               {\r
+                       tts->IPv6AcceptThread = NewThread(TtsIPv6AcceptThread, tts);\r
+               }\r
+\r
+               TtsAcceptProc(tts, tts->ListenSocket);\r
+\r
+               if (tts->IPv6AcceptThread != NULL)\r
+               {\r
+                       WaitThread(tts->IPv6AcceptThread, INFINITE);\r
+                       ReleaseThread(tts->IPv6AcceptThread);\r
+               }\r
+\r
+               TtPrint(tts->Param, tts->Print, _UU("TTS_LISTEN_STOP"));\r
+\r
+               ReleaseSock(tts->ListenSocket);\r
+               ReleaseSock(tts->ListenSocketV6);\r
+               SetSockEvent(tts->SockEvent);\r
+\r
+               // ワーカースレッドの停止を待機する\r
+               WaitThread(tts->WorkThread, INFINITE);\r
+               ReleaseThread(tts->WorkThread);\r
+               ReleaseSockEvent(tts->SockEvent);\r
+       }\r
+}\r
+\r
+// データが流れる方向の文字列\r
+wchar_t *GetTtcTypeStr(UINT type)\r
+{\r
+       switch (type)\r
+       {\r
+       case TRAFFIC_TYPE_DOWNLOAD:\r
+               return _UU("TTC_TYPE_DOWNLOAD");\r
+\r
+       case TRAFFIC_TYPE_UPLOAD:\r
+               return _UU("TTC_TYPE_UPLOAD");\r
+\r
+       default:\r
+               return _UU("TTC_TYPE_FULL");\r
+       }\r
+}\r
+\r
+// サマリーの表示\r
+void TtcPrintSummary(TTC *ttc)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       wchar_t tmp2[MAX_SIZE];\r
+       wchar_t *tag = L"%-35s %s";\r
+       // 引数チェック\r
+       if (ttc == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       TtPrint(ttc->Param, ttc->Print, L"");\r
+       TtPrint(ttc->Param, ttc->Print, _UU("TTC_SUMMARY_BAR"));\r
+       TtPrint(ttc->Param, ttc->Print, _UU("TTC_SUMMARY_TITLE"));\r
+       TtPrint(ttc->Param, ttc->Print, L"");\r
+\r
+       // 接続先のホスト名\r
+       StrToUni(tmp2, sizeof(tmp2), ttc->Host);\r
+       UniFormat(tmp, sizeof(tmp), tag, _UU("TTC_SUMMARY_HOST"), tmp2);\r
+       TtPrint(ttc->Param, ttc->Print, tmp);\r
+\r
+       // 接続先の TCP ポート番号\r
+       UniToStru(tmp2, ttc->Port);\r
+       UniFormat(tmp, sizeof(tmp), tag, _UU("TTC_SUMMARY_PORT"), tmp2);\r
+       TtPrint(ttc->Param, ttc->Print, tmp);\r
+\r
+       // 確立する TCP コネクション数\r
+       UniToStru(tmp2, ttc->NumTcp);\r
+       UniFormat(tmp, sizeof(tmp), tag, _UU("TTC_SUMMARY_NUMTCP"), tmp2);\r
+       TtPrint(ttc->Param, ttc->Print, tmp);\r
+\r
+       // データ伝送方向\r
+       UniFormat(tmp, sizeof(tmp), tag, _UU("TTC_SUMMARY_TYPE"), GetTtcTypeStr(ttc->Type));\r
+       TtPrint(ttc->Param, ttc->Print, tmp);\r
+\r
+       // データ伝送時間\r
+       UniFormat(tmp2, sizeof(tmp2), _UU("TTC_SPAN_STR"), (double)(ttc->Span) / 1000.0);\r
+       UniFormat(tmp, sizeof(tmp), tag, _UU("TTC_SUMMARY_SPAN"), tmp2);\r
+       TtPrint(ttc->Param, ttc->Print, tmp);\r
+\r
+       // Ethernet フレーム用にデータ補正\r
+       UniFormat(tmp, sizeof(tmp), tag, _UU("TTC_SUMMARY_ETHER"), ttc->Raw ? _UU("SEC_NO") : _UU("SEC_YES"));\r
+       TtPrint(ttc->Param, ttc->Print, tmp);\r
+\r
+       // 中継機器の入出力合計スループット計測\r
+       UniFormat(tmp, sizeof(tmp), tag, _UU("TTC_SUMMARY_DOUBLE"), ttc->Double ? _UU("SEC_YES") : _UU("SEC_NO"));\r
+       TtPrint(ttc->Param, ttc->Print, tmp);\r
+\r
+       TtPrint(ttc->Param, ttc->Print, _UU("TTC_SUMMARY_BAR"));\r
+       TtPrint(ttc->Param, ttc->Print, L"");\r
+}\r
+\r
+// 通信スループット測定クライアントの停止\r
+void StopTtc(TTC *ttc)\r
+{\r
+       // 引数チェック\r
+       if (ttc == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       TtPrint(ttc->Param, ttc->Print, _UU("TTC_STOPPING"));\r
+\r
+       ttc->Halt = true;\r
+       SetSockEvent(ttc->SockEvent);\r
+}\r
+\r
+// 結果を生成\r
+void TtcGenerateResult(TTC *ttc)\r
+{\r
+       TT_RESULT *res;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (ttc == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       res = &ttc->Result;\r
+\r
+       Zero(res, sizeof(TT_RESULT));\r
+\r
+       res->Raw = ttc->Raw;\r
+       res->Double = ttc->Double;\r
+       res->Span = ttc->RealSpan;\r
+\r
+       for (i = 0;i < LIST_NUM(ttc->ItcSockList);i++)\r
+       {\r
+               TTC_SOCK *ts = LIST_DATA(ttc->ItcSockList, i);\r
+\r
+               if (ts->Download == false)\r
+               {\r
+                       // アップロード\r
+                       res->NumBytesUpload += ts->NumBytes;\r
+               }\r
+               else\r
+               {\r
+                       // ダウンロード\r
+                       res->NumBytesDownload += ts->NumBytes;\r
+               }\r
+       }\r
+\r
+       if (res->Raw == false)\r
+       {\r
+               // Ethernet に合わせて補正する\r
+               // (1 個の Ethernet フレーム中の最大の TCP ペイロードサイズは 1460 である。)\r
+               res->NumBytesDownload = (UINT64)((double)res->NumBytesDownload * 1514.0 / 1460.0);\r
+               res->NumBytesUpload = (UINT64)((double)res->NumBytesUpload * 1514.0 / 1460.0);\r
+       }\r
+\r
+       res->NumBytesTotal = res->NumBytesDownload + res->NumBytesUpload;\r
+\r
+       // スループットを計測する\r
+       if (res->Span != 0)\r
+       {\r
+               res->BpsUpload = (UINT64)((double)res->NumBytesUpload * 8.0 / ((double)res->Span / 1000.0));\r
+               res->BpsDownload = (UINT64)((double)res->NumBytesDownload * 8.0 / ((double)res->Span / 1000.0));\r
+       }\r
+\r
+       if (res->Double)\r
+       {\r
+               res->BpsUpload *= 2ULL;\r
+               res->BpsDownload *= 2ULL;\r
+       }\r
+\r
+       res->BpsTotal = res->BpsUpload + res->BpsDownload;\r
+}\r
+\r
+// クライアントスレッド\r
+void TtcThread(THREAD *thread, void *param)\r
+{\r
+       TTC *ttc;\r
+       UINT i;\r
+       wchar_t tmp[MAX_SIZE];\r
+       bool ok = false;\r
+       UINT buf_size;\r
+       UCHAR *send_buf_data, *recv_buf_data;\r
+       // 引数チェック\r
+       if (thread == NULL || param == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // データ領域の確保\r
+       TtGenerateRandomData(&send_buf_data, &buf_size);\r
+       TtGenerateRandomData(&recv_buf_data, &buf_size);\r
+\r
+       ttc = (TTC *)param;\r
+\r
+       ttc->SockEvent = NewSockEvent();\r
+       AddRef(ttc->SockEvent->ref);\r
+\r
+       // 準備完了\r
+       NoticeThreadInit(thread);\r
+\r
+       TtcPrintSummary(ttc);\r
+\r
+       UniFormat(tmp, sizeof(tmp), _UU("TTC_CONNECT_START"),\r
+               ttc->Host, ttc->Port, ttc->NumTcp);\r
+       TtPrint(ttc->Param, ttc->Print, tmp);\r
+\r
+       // クライアントへのすべてのコネクションを確立する\r
+       ttc->ItcSockList = NewList(NULL);\r
+\r
+       ok = true;\r
+\r
+       for (i = 0;i < ttc->NumTcp;i++)\r
+       {\r
+               SOCK *s;\r
+               TTC_SOCK *ts = ZeroMalloc(sizeof(TTC_SOCK));\r
+\r
+               ts->Id = i + 1;\r
+\r
+               if (ttc->Type == TRAFFIC_TYPE_DOWNLOAD)\r
+               {\r
+                       ts->Download = true;\r
+               }\r
+               else if (ttc->Type == TRAFFIC_TYPE_UPLOAD)\r
+               {\r
+                       ts->Download = false;\r
+               }\r
+               else\r
+               {\r
+                       ts->Download = ((i % 2) == 0) ? true : false;\r
+               }\r
+\r
+               s = Connect(ttc->Host, ttc->Port);\r
+\r
+               if (s == NULL)\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("TTC_CONNECT_FAILED"), i + 1);\r
+                       TtPrint(ttc->Param, ttc->Print, tmp);\r
+                       ok = false;\r
+                       Free(ts);\r
+                       break;\r
+               }\r
+               else\r
+               {\r
+                       char buffer[TRAFFIC_VER_STR_SIZE];\r
+\r
+                       SetTimeout(s, 5000);\r
+\r
+                       Zero(buffer, sizeof(buffer));\r
+                       if (Recv(s, buffer, sizeof(buffer), false) != sizeof(buffer) || Cmp(buffer, TRAFFIC_VER_STR, TRAFFIC_VER_STR_SIZE) != 0)\r
+                       {\r
+                               TtPrint(ttc->Param, ttc->Print, _UU("TTC_CONNECT_NOT_SERVER"));\r
+                               ok = false;\r
+                               ReleaseSock(s);\r
+                               Free(ts);\r
+                               break;\r
+                       }\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("TTC_CONNECT_OK"), i + 1);\r
+                       TtPrint(ttc->Param, ttc->Print, tmp);\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("TTC_CONNECT_OK_2"), GetTtcTypeStr(ts->Download ? TRAFFIC_TYPE_DOWNLOAD : TRAFFIC_TYPE_UPLOAD));\r
+                       TtPrint(ttc->Param, ttc->Print, tmp);\r
+\r
+                       ts->Sock = s;\r
+\r
+                       SetTimeout(s, TIMEOUT_INFINITE);\r
+\r
+                       JoinSockToSockEvent(s, ttc->SockEvent);\r
+               }\r
+\r
+               Insert(ttc->ItcSockList, ts);\r
+       }\r
+\r
+       Set(ttc->InitedEvent);\r
+\r
+       if (ttc->StartEvent != NULL)\r
+       {\r
+               Wait(ttc->StartEvent, INFINITE);\r
+               SleepThread(500);\r
+       }\r
+\r
+       if (ok)\r
+       {\r
+               bool all_sockets_blocked;\r
+               bool dont_block_next_time = false;\r
+               bool halt_flag = false;\r
+               UINT64 start_tick, end_tick;\r
+               UINT64 halt_timeout = 0;\r
+               wchar_t tmp1[MAX_SIZE], tmp2[MAX_SIZE];\r
+               UINT check_clock_seed = 0;\r
+               bool halting = false;\r
+               UINT64 tmp64;\r
+\r
+               // 現在時刻を記録\r
+               start_tick = Tick64();\r
+               end_tick = start_tick + ttc->Span;\r
+\r
+               // 開始メッセージを表示\r
+               GetDateTimeStrEx64(tmp1, sizeof(tmp1), SystemToLocal64(TickToTime(start_tick)), NULL);\r
+               GetDateTimeStrEx64(tmp2, sizeof(tmp2), SystemToLocal64(TickToTime(end_tick)), NULL);\r
+               UniFormat(tmp, sizeof(tmp), _UU("TTC_COMM_START"), tmp1, tmp2);\r
+               TtPrint(ttc->Param, ttc->Print, tmp);\r
+\r
+               // メインループ\r
+               while (true)\r
+               {\r
+                       UINT i;\r
+\r
+                       if (dont_block_next_time == false)\r
+                       {\r
+                               WaitSockEvent(ttc->SockEvent, 50);\r
+                       }\r
+\r
+                       dont_block_next_time = false;\r
+\r
+                       if (ttc->AbnormalTerminated)\r
+                       {\r
+                               // 異常終了が発生した\r
+                               break;\r
+                       }\r
+\r
+                       if (ttc->Halt || end_tick <= Tick64())\r
+                       {\r
+                               // 計測終了\r
+                               if (halting == false)\r
+                               {\r
+                                       if (ttc->Halt)\r
+                                       {\r
+                                               // ユーザーキャンセル\r
+                                               TtPrint(ttc->Param, ttc->Print, _UU("TTC_COMM_USER_CANCEL"));\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               // 時間経過\r
+                                               UniFormat(tmp, sizeof(tmp), _UU("TTC_COMM_END"),\r
+                                                       (double)ttc->Span / 1000.0);\r
+                                               TtPrint(ttc->Param, ttc->Print, tmp);\r
+                                       }\r
+\r
+                                       ttc->RealSpan = Tick64() - start_tick;\r
+\r
+                                       halting = true;\r
+\r
+                                       // サーバーからの報告データを待つ\r
+                                       halt_timeout = Tick64() + 60000ULL;\r
+                               }\r
+                       }\r
+\r
+                       if (halt_timeout != 0)\r
+                       {\r
+                               bool ok = true;\r
+\r
+                               // すべての TCP コネクションが処理を完了するまで待機する\r
+                               for (i = 0;i < LIST_NUM(ttc->ItcSockList);i++)\r
+                               {\r
+                                       TTC_SOCK *ts = LIST_DATA(ttc->ItcSockList, i);\r
+\r
+                                       if (ts->Download == false)\r
+                                       {\r
+                                               if (ts->ServerUploadReportReceived == false)\r
+                                               {\r
+                                                       ok = false;\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               if (ok)\r
+                               {\r
+                                       // 測定完了\r
+                                       // 結果を表示する\r
+                                       TtcGenerateResult(ttc);\r
+                                       break;\r
+                               }\r
+                               else\r
+                               {\r
+                                       if (halt_timeout <= Tick64())\r
+                                       {\r
+                                               // 異常発生\r
+                                               ttc->AbnormalTerminated = true;\r
+                                               ttc->ErrorCode = ERR_PROTOCOL_ERROR;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       all_sockets_blocked = false;\r
+\r
+                       // すべてのソケットがブロック状態にならない限り\r
+                       // データの送受信を続ける\r
+                       while (all_sockets_blocked == false)\r
+                       {\r
+                               all_sockets_blocked = true;\r
+\r
+                               for (i = 0;i < LIST_NUM(ttc->ItcSockList);i++)\r
+                               {\r
+                                       UINT ret = SOCK_LATER;\r
+                                       TTC_SOCK *ts = LIST_DATA(ttc->ItcSockList, i);\r
+                                       bool blocked_for_this_socket = false;\r
+                                       UCHAR c = 0;\r
+\r
+                                       if (halt_timeout != 0)\r
+                                       {\r
+                                               if (ts->State != 3 && ts->State != 4)\r
+                                               {\r
+                                                       if (ts->Download == false)\r
+                                                       {\r
+                                                               if (ts->State != 0)\r
+                                                               {\r
+                                                                       ts->State = 3;\r
+                                                               }\r
+                                                               else\r
+                                                               {\r
+                                                                       ts->ServerUploadReportReceived = true;\r
+                                                                       ts->State = 4;\r
+                                                               }\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               ts->State = 4;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+\r
+                                       switch (ts->State)\r
+                                       {\r
+                                       case 0:\r
+                                               // 初期状態: クライアント/サーバー間のデータの流れの\r
+                                               // 方向を指定する\r
+                                               if (ts->Download)\r
+                                               {\r
+                                                       c = 1;\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       c = 0;\r
+                                               }\r
+\r
+                                               ret = Send(ts->Sock, &c, 1, false);\r
+\r
+                                               if (ret != 0 && ret != SOCK_LATER)\r
+                                               {\r
+                                                       if (ts->Download)\r
+                                                       {\r
+                                                               ts->State = 1;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               ts->State = 2;\r
+                                                       }\r
+                                               }\r
+                                               break;\r
+\r
+                                       case 1:\r
+                                               // サーバー -> クライアント (ダウンロード)\r
+                                               ret = Recv(ts->Sock, recv_buf_data, buf_size, false);\r
+                                               break;\r
+\r
+                                       case 2:\r
+                                               // クライアント -> サーバー (アップロード)\r
+                                               ret = Send(ts->Sock, send_buf_data, buf_size, false);\r
+                                               break;\r
+\r
+                                       case 3:\r
+                                               // クライアント -> サーバー (アップロード) の送信完了\r
+                                               // データサイズの要求処理\r
+                                               if (ts->NextSendRequestReportTick == 0 ||\r
+                                                       (Tick64() >= ts->NextSendRequestReportTick))\r
+                                               {\r
+                                                       UCHAR suprise[MAX_SIZE];\r
+                                                       UINT i;\r
+\r
+                                                       ts->NextSendRequestReportTick = Tick64() + 200ULL;\r
+\r
+                                                       for (i = 0;i < sizeof(suprise);i++)\r
+                                                       {\r
+                                                               suprise[i] = '!';\r
+                                                       }\r
+\r
+                                                       ret = Send(ts->Sock, suprise, sizeof(suprise), false);\r
+                                               }\r
+\r
+                                               ret = Recv(ts->Sock, &tmp64, sizeof(tmp64), false);\r
+                                               if (ret != 0 && ret != SOCK_LATER && ret == sizeof(tmp64))\r
+                                               {\r
+                                                       ts->NumBytes = Endian64(tmp64);\r
+\r
+                                                       ts->ServerUploadReportReceived = true;\r
+\r
+                                                       ts->State = 4;\r
+                                               }\r
+                                               break;\r
+\r
+                                       case 4:\r
+                                               // 何もしない\r
+                                               if (Recv(ts->Sock, recv_buf_data, buf_size, false) == SOCK_LATER)\r
+                                               {\r
+                                                       ret = SOCK_LATER;\r
+                                               }\r
+                                               break;\r
+                                       }\r
+\r
+                                       if (ret == 0)\r
+                                       {\r
+                                               // ソケットが切断された\r
+                                               ttc->AbnormalTerminated = true;\r
+                                               ttc->ErrorCode = ERR_PROTOCOL_ERROR;\r
+                                               blocked_for_this_socket = true;\r
+                                               dont_block_next_time = false;\r
+\r
+                                               UniFormat(tmp, sizeof(tmp), _UU("TTC_COMM_DISCONNECTED"), ts->Id);\r
+                                               TtPrint(ttc->Param, ttc->Print, tmp);\r
+                                       }\r
+                                       else if (ret == SOCK_LATER)\r
+                                       {\r
+                                               // 遅延が発生した\r
+                                               blocked_for_this_socket = true;\r
+                                               dont_block_next_time = false;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               if (ts->Download)\r
+                                               {\r
+                                                       ts->NumBytes += (UINT64)ret;\r
+                                               }\r
+                                       }\r
+\r
+                                       if (blocked_for_this_socket == false)\r
+                                       {\r
+                                               all_sockets_blocked = false;\r
+                                       }\r
+                               }\r
+\r
+                               if (ttc->Halt)\r
+                               {\r
+                                       all_sockets_blocked = true;\r
+                                       dont_block_next_time = true;\r
+                               }\r
+\r
+                               if (end_tick <= Tick64())\r
+                               {\r
+                                       all_sockets_blocked = true;\r
+                                       dont_block_next_time = true;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               // 中止\r
+               TtPrint(ttc->Param, ttc->Print, _UU("TTC_ERROR_ABORTED"));\r
+               ttc->ErrorCode = ERR_CONNECT_FAILED;\r
+       }\r
+\r
+       // クリーンアップ\r
+       for (i = 0;i < LIST_NUM(ttc->ItcSockList);i++)\r
+       {\r
+               TTC_SOCK *ts = LIST_DATA(ttc->ItcSockList, i);\r
+\r
+               Disconnect(ts->Sock);\r
+               ReleaseSock(ts->Sock);\r
+               Free(ts);\r
+       }\r
+\r
+       ReleaseSockEvent(ttc->SockEvent);\r
+       ReleaseList(ttc->ItcSockList);\r
+       Free(send_buf_data);\r
+       Free(recv_buf_data);\r
+}\r
+\r
+// 通信スループット測定クライアントの開始\r
+TTC *NewTtc(char *host, UINT port, UINT numtcp, UINT type, UINT64 span, bool dbl, bool raw, TT_PRINT_PROC *print_proc, void *param)\r
+{\r
+       return NewTtcEx(host, port, numtcp, type, span, dbl, raw, print_proc, param, NULL);\r
+}\r
+TTC *NewTtcEx(char *host, UINT port, UINT numtcp, UINT type, UINT64 span, bool dbl, bool raw, TT_PRINT_PROC *print_proc, void *param, EVENT *start_event)\r
+{\r
+       TTC *ttc;\r
+\r
+       ttc = ZeroMalloc(sizeof(TTC));\r
+       ttc->InitedEvent = NewEvent();\r
+       ttc->Port = port;\r
+       StrCpy(ttc->Host, sizeof(ttc->Host), host);\r
+       ttc->NumTcp = numtcp;\r
+       ttc->Type = type;\r
+       ttc->Span = span;\r
+       ttc->Double = dbl;\r
+       ttc->Raw = raw;\r
+       ttc->StartEvent = start_event;\r
+\r
+       if (ttc->Type == TRAFFIC_TYPE_FULL && ttc->NumTcp < 2)\r
+       {\r
+               ttc->NumTcp = 2;\r
+       }\r
+\r
+       ttc->Print = print_proc;\r
+       ttc->Param = param;\r
+       ttc->ErrorCode = ERR_NO_ERROR;\r
+\r
+       TtPrint(ttc->Param, ttc->Print, _UU("TTC_INIT"));\r
+\r
+       ttc->Thread = NewThread(TtcThread, ttc);\r
+       WaitThreadInit(ttc->Thread);\r
+\r
+       return ttc;\r
+}\r
+\r
+// 通信スループット測定クライアントの終了を待機\r
+UINT FreeTtc(TTC *ttc, TT_RESULT *result)\r
+{\r
+       UINT ret;\r
+       // 引数チェック\r
+       if (ttc == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       WaitThread(ttc->Thread, INFINITE);\r
+       ReleaseThread(ttc->Thread);\r
+\r
+       TtPrint(ttc->Param, ttc->Print, _UU("TTC_FREE"));\r
+\r
+       ret = ttc->ErrorCode;\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               if (result != NULL)\r
+               {\r
+                       Copy(result, &ttc->Result, sizeof(TT_RESULT));\r
+               }\r
+       }\r
+\r
+       ReleaseSockEvent(ttc->SockEvent);\r
+       ReleaseEvent(ttc->InitedEvent);\r
+\r
+       Free(ttc);\r
+\r
+       return ret;\r
+}\r
+\r
+// 通信スループット測定サーバーの開始\r
+TTS *NewTts(UINT port, void *param, TT_PRINT_PROC *print_proc)\r
+{\r
+       TTS *tts;\r
+       THREAD *t;\r
+\r
+       tts = ZeroMalloc(sizeof(TTS));\r
+       tts->Port = port;\r
+       tts->Param = param;\r
+       tts->Print = print_proc;\r
+\r
+       TtPrint(param, print_proc, _UU("TTS_INIT"));\r
+\r
+       // スレッドの作成\r
+       t = NewThread(TtsListenThread, tts);\r
+       WaitThreadInit(t);\r
+\r
+       tts->Thread = t;\r
+\r
+       return tts;\r
+}\r
+\r
+// 通信スループット測定サーバーの終了を待機\r
+UINT FreeTts(TTS *tts)\r
+{\r
+       UINT ret;\r
+       // 引数チェック\r
+       if (tts == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       TtPrint(tts->Param, tts->Print, _UU("TTS_STOP_INIT"));\r
+\r
+       tts->Halt = true;\r
+       Disconnect(tts->ListenSocket);\r
+       ReleaseSock(tts->ListenSocket);\r
+       Disconnect(tts->ListenSocketV6);\r
+       ReleaseSock(tts->ListenSocketV6);\r
+\r
+       // スレッドの終了を待機\r
+       WaitThread(tts->Thread, INFINITE);\r
+\r
+       ReleaseThread(tts->Thread);\r
+\r
+       TtPrint(tts->Param, tts->Print, _UU("TTS_STOP_FINISHED"));\r
+\r
+       ret = tts->ErrorCode;\r
+\r
+       Free(tts);\r
+\r
+       return ret;\r
+}\r
+\r
+// 測定ツールプロンプトの表示\r
+void PtTrafficPrintProc(void *param, wchar_t *str)\r
+{\r
+       CONSOLE *c;\r
+       // 引数チェック\r
+       if (param == NULL || str == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       c = (CONSOLE *)param;\r
+\r
+       if (c->ConsoleType == CONSOLE_LOCAL)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+\r
+               // ローカルコンソールの場合のみ表示する (それ以外の場合はマルチスレッドの同期\r
+               //  がとれないので表示できない?)\r
+               UniStrCpy(tmp, sizeof(tmp), str);\r
+               if (UniEndWith(str, L"\n") == false)\r
+               {\r
+                       UniStrCat(tmp, sizeof(tmp), L"\n");\r
+               }\r
+               UniPrint(L"%s", tmp);\r
+       }\r
+}\r
+\r
+// 通信スループット結果の表示\r
+void TtcPrintResult(CONSOLE *c, TT_RESULT *res)\r
+{\r
+       CT *ct;\r
+       wchar_t tmp[MAX_SIZE];\r
+       wchar_t tmp1[MAX_SIZE];\r
+       wchar_t tmp2[MAX_SIZE];\r
+       char str[MAX_SIZE];\r
+       // 引数チェック\r
+       if (c == NULL || res == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       c->Write(c, _UU("TTC_RES_TITLE"));\r
+\r
+       ct = CtNew();\r
+       CtInsertColumn(ct, _UU("TTC_RES_COLUMN_1"), false);\r
+       CtInsertColumn(ct, _UU("TTC_RES_COLUMN_2"), true);\r
+       CtInsertColumn(ct, _UU("TTC_RES_COLUMN_3"), true);\r
+\r
+       // 測定に使用した時間\r
+       GetSpanStrMilli(str, sizeof(str), res->Span);\r
+       StrToUni(tmp, sizeof(tmp), str);\r
+       CtInsert(ct, _UU("TTC_RES_SPAN"), tmp, L"");\r
+\r
+       // Ethernet フレーム用にデータ補正\r
+       CtInsert(ct, _UU("TTC_RES_ETHER"), res->Raw ? _UU("SEC_NO") : _UU("SEC_YES"), L"");\r
+\r
+       // ダウンロード方向の通信データ量\r
+       ToStr3(str, sizeof(str), res->NumBytesDownload);\r
+       UniFormat(tmp1, sizeof(tmp1), L"%S Bytes", str);\r
+       ToStrByte1000(str, sizeof(str), res->NumBytesDownload);\r
+       StrToUni(tmp2, sizeof(tmp2), str);\r
+       CtInsert(ct, _UU("TTC_RES_BYTES_DOWNLOAD"), tmp1, tmp2);\r
+\r
+       // アップロード方向の通信データ量\r
+       ToStr3(str, sizeof(str), res->NumBytesUpload);\r
+       UniFormat(tmp1, sizeof(tmp1), L"%S Bytes", str);\r
+       ToStrByte1000(str, sizeof(str), res->NumBytesUpload);\r
+       StrToUni(tmp2, sizeof(tmp2), str);\r
+       CtInsert(ct, _UU("TTC_RES_BYTES_UPLOAD"), tmp1, tmp2);\r
+\r
+       // 合計通信データ量\r
+       ToStr3(str, sizeof(str), res->NumBytesTotal);\r
+       UniFormat(tmp1, sizeof(tmp1), L"%S Bytes", str);\r
+       ToStrByte1000(str, sizeof(str), res->NumBytesTotal);\r
+       StrToUni(tmp2, sizeof(tmp2), str);\r
+       CtInsert(ct, _UU("TTC_RES_BYTES_TOTAL"), tmp1, tmp2);\r
+\r
+       // 中継機器入出力合計スループット算出\r
+       CtInsert(ct, _UU("TTC_RES_DOUBLE"), (res->Double == false) ? _UU("SEC_NO") : _UU("SEC_YES"), L"");\r
+\r
+       // ダウンロード方向の平均スループット\r
+       ToStr3(str, sizeof(str), res->BpsDownload);\r
+       UniFormat(tmp1, sizeof(tmp1), L"%S bps", str);\r
+       ToStrByte1000(str, sizeof(str), res->BpsDownload);\r
+       ReplaceStr(str, sizeof(str), str, "Bytes", "bps");\r
+       StrToUni(tmp2, sizeof(tmp2), str);\r
+       CtInsert(ct, _UU("TTC_RES_BPS_DOWNLOAD"), tmp1, tmp2);\r
+\r
+       // アップロード方向の平均スループット\r
+       ToStr3(str, sizeof(str), res->BpsUpload);\r
+       UniFormat(tmp1, sizeof(tmp1), L"%S bps", str);\r
+       ToStrByte1000(str, sizeof(str), res->BpsUpload);\r
+       ReplaceStr(str, sizeof(str), str, "Bytes", "bps");\r
+       StrToUni(tmp2, sizeof(tmp2), str);\r
+       CtInsert(ct, _UU("TTC_RES_BPS_UPLOAD"), tmp1, tmp2);\r
+\r
+       // 合計平均スループット\r
+       ToStr3(str, sizeof(str), res->BpsTotal);\r
+       UniFormat(tmp1, sizeof(tmp1), L"%S bps", str);\r
+       ToStrByte1000(str, sizeof(str), res->BpsTotal);\r
+       ReplaceStr(str, sizeof(str), str, "Bytes", "bps");\r
+       StrToUni(tmp2, sizeof(tmp2), str);\r
+       CtInsert(ct, _UU("TTC_RES_BPS_TOTAL"), tmp1, tmp2);\r
+\r
+       CtFree(ct, c);\r
+}\r
+\r
+// 通信スループット測定ツールサーバーの実行\r
+UINT PtTrafficServer(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       UINT ret = ERR_NO_ERROR;\r
+       UINT port;\r
+       TTS *tts;\r
+       PARAM args[] =\r
+       {\r
+               {"[port]", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       port = GetParamInt(o, "[port]");\r
+       if (port == 0)\r
+       {\r
+               port = TRAFFIC_DEFAULT_PORT;\r
+       }\r
+\r
+       tts = NewTts(port, c, PtTrafficPrintProc);\r
+\r
+       c->Write(c, _UU("TTS_ENTER_TO_EXIT"));\r
+\r
+       Free(c->ReadLine(c, L"", true));\r
+\r
+       ret = tts->ErrorCode;\r
+\r
+       FreeTts(tts);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 通信スループット測定ツールクライアントの実行\r
+UINT PtTrafficClient(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       TTC *ttc;\r
+       LIST *o;\r
+       UINT ret = ERR_NO_ERROR;\r
+       char *host = NULL;\r
+       UINT port;\r
+       UINT num, type;\r
+       bool dbl = false, raw = false;\r
+       UINT64 span;\r
+       // 指定できるパラメータ リスト\r
+       CMD_EVAL_MIN_MAX minmax =\r
+       {\r
+               "CMD_TrafficClient_EVAL_NUMTCP",\r
+               0, TRAFFIC_NUMTCP_MAX,\r
+       };\r
+       PARAM args[] =\r
+       {\r
+               {"[host:port]", CmdPrompt, _UU("CMD_TrafficClient_PROMPT_HOST"), CmdEvalNotEmpty, NULL},\r
+               {"NUMTCP", NULL, NULL, CmdEvalMinMax, &minmax},\r
+               {"TYPE", NULL, NULL, NULL, NULL},\r
+               {"SPAN", NULL, NULL, NULL, NULL},\r
+               {"DOUBLE", NULL, NULL, NULL, NULL},\r
+               {"RAW", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (ParseHostPort(GetParamStr(o, "[host:port]"), &host, &port, TRAFFIC_DEFAULT_PORT) == false)\r
+       {\r
+               c->Write(c, _UU("CMD_TrafficClient_ERROR_HOSTPORT"));\r
+               ret = ERR_INVALID_PARAMETER;\r
+       }\r
+       else\r
+       {\r
+               char *s;\r
+               UINT i;\r
+\r
+               Trim(host);\r
+\r
+               num = GetParamInt(o, "NUMTCP");\r
+               if (num == 0)\r
+               {\r
+                       num = TRAFFIC_NUMTCP_DEFAULT;\r
+               }\r
+               s = GetParamStr(o, "TYPE");\r
+\r
+               if (StartWith("download", s))\r
+               {\r
+                       type = TRAFFIC_TYPE_DOWNLOAD;\r
+               }\r
+               else if (StartWith("upload", s))\r
+               {\r
+                       type = TRAFFIC_TYPE_UPLOAD;\r
+               }\r
+               else\r
+               {\r
+                       type = TRAFFIC_TYPE_FULL;\r
+               }\r
+\r
+               i = GetParamInt(o, "SPAN");\r
+\r
+               if (i == 0)\r
+               {\r
+                       i = TRAFFIC_SPAN_DEFAULT;\r
+               }\r
+\r
+               span = (UINT64)i * 1000ULL;\r
+\r
+               dbl = GetParamYes(o, "DOUBLE");\r
+               raw = GetParamYes(o, "RAW");\r
+\r
+               if (type == TRAFFIC_TYPE_FULL)\r
+               {\r
+                       if ((num % 2) != 0)\r
+                       {\r
+                               ret = ERR_INVALID_PARAMETER;\r
+                               c->Write(c, _UU("CMD_TrafficClient_ERROR_NUMTCP"));\r
+                       }\r
+               }\r
+\r
+               if (ret == ERR_NO_ERROR)\r
+               {\r
+                       TT_RESULT result;\r
+                       ttc = NewTtc(host, port, num, type, span, dbl, raw, PtTrafficPrintProc, c);\r
+\r
+                       if (c->ConsoleType == CONSOLE_LOCAL)\r
+                       {\r
+                               if (c->Param != NULL && (((LOCAL_CONSOLE_PARAM *)c->Param)->InBuf == NULL))\r
+                               {\r
+//                                     c->Write(c, _UU("TTC_ENTER_TO_EXIT"));\r
+//                                     GetLine(NULL, 0);\r
+//                                     StopTtc(ttc);\r
+                               }\r
+                       }\r
+\r
+\r
+                       Zero(&result, sizeof(result));\r
+                       ret = FreeTtc(ttc, &result);\r
+\r
+                       if (ret == ERR_NO_ERROR)\r
+                       {\r
+                               TtcPrintResult(c, &result);\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       Free(host);\r
+\r
+       return ret;\r
+}\r
+\r
+// 証明書簡易作成ツール\r
+UINT PtMakeCert(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       UINT ret = ERR_NO_ERROR;\r
+       X *x = NULL;\r
+       K *pub = NULL;\r
+       K *pri = NULL;\r
+       NAME *n;\r
+       X_SERIAL *x_serial = NULL;\r
+       BUF *buf;\r
+       UINT days;\r
+       X *root_x = NULL;\r
+       K *root_k = NULL;\r
+       // 指定できるパラメータ リスト\r
+       CMD_EVAL_MIN_MAX minmax =\r
+       {\r
+               "CMD_MakeCert_EVAL_EXPIRES",\r
+               0,\r
+               10950,\r
+       };\r
+       PARAM args[] =\r
+       {\r
+               {"CN", CmdPrompt, _UU("CMD_MakeCert_PROMPT_CN"), NULL, NULL},\r
+               {"O", CmdPrompt, _UU("CMD_MakeCert_PROMPT_O"), NULL, NULL},\r
+               {"OU", CmdPrompt, _UU("CMD_MakeCert_PROMPT_OU"), NULL, NULL},\r
+               {"C", CmdPrompt, _UU("CMD_MakeCert_PROMPT_C"), NULL, NULL},\r
+               {"ST", CmdPrompt, _UU("CMD_MakeCert_PROMPT_ST"), NULL, NULL},\r
+               {"L", CmdPrompt, _UU("CMD_MakeCert_PROMPT_L"), NULL, NULL},\r
+               {"SERIAL", CmdPrompt, _UU("CMD_MakeCert_PROMPT_SERIAL"), NULL, NULL},\r
+               {"EXPIRES", CmdPrompt, _UU("CMD_MakeCert_PROMPT_EXPIRES"), CmdEvalMinMax, &minmax},\r
+               {"SIGNCERT", NULL, NULL, CmdEvalIsFile, NULL},\r
+               {"SIGNKEY", NULL, NULL, CmdEvalIsFile, NULL},\r
+               {"SAVECERT", CmdPrompt, _UU("CMD_MakeCert_PROMPT_SAVECERT"), CmdEvalNotEmpty, NULL},\r
+               {"SAVEKEY", CmdPrompt, _UU("CMD_MakeCert_PROMPT_SAVEKEY"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (IsEmptyStr(GetParamStr(o, "SIGNCERT")) == false && IsEmptyStr(GetParamStr(o, "SIGNKEY")) == false)\r
+       {\r
+               root_x = FileToX(GetParamStr(o, "SIGNCERT"));\r
+               root_k = FileToK(GetParamStr(o, "SIGNKEY"), true, NULL);\r
+\r
+               if (root_x == NULL || root_k == NULL || CheckXandK(root_x, root_k) == false)\r
+               {\r
+                       ret = ERR_INTERNAL_ERROR;\r
+\r
+                       c->Write(c, _UU("CMD_MakeCert_ERROR_SIGNKEY"));\r
+               }\r
+       }\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               buf = StrToBin(GetParamStr(o, "SERIAL"));\r
+               if (buf != NULL && buf->Size >= 1)\r
+               {\r
+                       x_serial = NewXSerial(buf->Buf, buf->Size);\r
+               }\r
+               FreeBuf(buf);\r
+\r
+               n = NewName(GetParamUniStr(o, "CN"), GetParamUniStr(o, "O"), GetParamUniStr(o, "OU"), \r
+                       GetParamUniStr(o, "C"), GetParamUniStr(o, "ST"), GetParamUniStr(o, "L"));\r
+\r
+               days = GetParamInt(o, "EXPIRES");\r
+               if (days == 0)\r
+               {\r
+                       days = 3650;\r
+               }\r
+\r
+               RsaGen(&pri, &pub, 1024);\r
+\r
+               if (root_x == NULL)\r
+               {\r
+                       x = NewRootX(pub, pri, n, days, x_serial);\r
+               }\r
+               else\r
+               {\r
+                       x = NewX(pub, root_k, root_x, n, days, x_serial);\r
+               }\r
+\r
+               FreeXSerial(x_serial);\r
+               FreeName(n);\r
+\r
+               if (x == NULL)\r
+               {\r
+                       ret = ERR_INTERNAL_ERROR;\r
+                       c->Write(c, _UU("CMD_MakeCert_ERROR_GEN_FAILED"));\r
+               }\r
+               else\r
+               {\r
+                       if (XToFile(x, GetParamStr(o, "SAVECERT"), true) == false)\r
+                       {\r
+                               c->Write(c, _UU("CMD_SAVECERT_FAILED"));\r
+                       }\r
+                       else if (KToFile(pri, GetParamStr(o, "SAVEKEY"), true, NULL) == false)\r
+                       {\r
+                               c->Write(c, _UU("CMD_SAVEKEY_FAILED"));\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       FreeX(root_x);\r
+       FreeK(root_k);\r
+\r
+       FreeX(x);\r
+       FreeK(pri);\r
+       FreeK(pub);\r
+\r
+       return ret;\r
+}\r
+\r
+\r
+// クライアント管理ツールメイン\r
+void PcMain(PC *pc)\r
+{\r
+       char prompt[MAX_SIZE];\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (pc == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 接続が完了したメッセージを表示する\r
+       UniFormat(tmp, sizeof(tmp), _UU("CMD_UTVPNCMD_CLIENT_CONNECTED"),\r
+               pc->ServerName);\r
+       pc->Console->Write(pc->Console, tmp);\r
+       pc->Console->Write(pc->Console, L"");\r
+\r
+       while (true)\r
+       {\r
+               // コマンドの定義\r
+               CMD cmd[] =\r
+               {\r
+                       {"About", PsAbout},\r
+                       {"Check", PtCheck},\r
+                       {"VersionGet", PcVersionGet},\r
+                       {"PasswordSet", PcPasswordSet},\r
+                       {"PasswordGet", PcPasswordGet},\r
+                       {"CertList", PcCertList},\r
+                       {"CertAdd", PcCertAdd},\r
+                       {"CertDelete", PcCertDelete},\r
+                       {"CertGet", PcCertGet},\r
+                       {"SecureList", PcSecureList},\r
+                       {"SecureSelect", PcSecureSelect},\r
+                       {"SecureGet", PcSecureGet},\r
+                       {"NicCreate", PcNicCreate},\r
+                       {"NicDelete", PcNicDelete},\r
+                       {"NicUpgrade", PcNicUpgrade},\r
+                       {"NicGetSetting", PcNicGetSetting},\r
+                       {"NicSetSetting", PcNicSetSetting},\r
+                       {"NicEnable", PcNicEnable},\r
+                       {"NicDisable", PcNicDisable},\r
+                       {"NicList", PcNicList},\r
+                       {"AccountList", PcAccountList},\r
+                       {"AccountCreate", PcAccountCreate},\r
+                       {"AccountSet", PcAccountSet},\r
+                       {"AccountGet", PcAccountGet},\r
+                       {"AccountDelete", PcAccountDelete},\r
+                       {"AccountUsernameSet", PcAccountUsernameSet},\r
+                       {"AccountAnonymousSet", PcAccountAnonymousSet},\r
+                       {"AccountPasswordSet", PcAccountPasswordSet},\r
+                       {"AccountCertSet", PcAccountCertSet},\r
+                       {"AccountCertGet", PcAccountCertGet},\r
+                       {"AccountEncryptDisable", PcAccountEncryptDisable},\r
+                       {"AccountEncryptEnable", PcAccountEncryptEnable},\r
+                       {"AccountCompressEnable", PcAccountCompressEnable},\r
+                       {"AccountCompressDisable", PcAccountCompressDisable},\r
+                       {"AccountProxyNone", PcAccountProxyNone},\r
+                       {"AccountProxyHttp", PcAccountProxyHttp},\r
+                       {"AccountProxySocks", PcAccountProxySocks},\r
+                       {"AccountServerCertEnable", PcAccountServerCertEnable},\r
+                       {"AccountServerCertDisable", PcAccountServerCertDisable},\r
+                       {"AccountServerCertSet", PcAccountServerCertSet},\r
+                       {"AccountServerCertDelete", PcAccountServerCertDelete},\r
+                       {"AccountServerCertGet", PcAccountServerCertGet},\r
+                       {"AccountDetailSet", PcAccountDetailSet},\r
+                       {"AccountRename", PcAccountRename},\r
+                       {"AccountConnect", PcAccountConnect},\r
+                       {"AccountDisconnect", PcAccountDisconnect},\r
+                       {"AccountStatusGet", PcAccountStatusGet},\r
+                       {"AccountNicSet", PcAccountNicSet},\r
+                       {"AccountStatusShow", PcAccountStatusShow},\r
+                       {"AccountStatusHide", PcAccountStatusHide},\r
+                       {"AccountSecureCertSet", PcAccountSecureCertSet},\r
+                       {"AccountRetrySet", PcAccountRetrySet},\r
+                       {"AccountStartupSet", PcAccountStartupSet},\r
+                       {"AccountStartupRemove", PcAccountStartupRemove},\r
+                       {"AccountExport", PcAccountExport},\r
+                       {"AccountImport", PcAccountImport},\r
+                       {"RemoteEnable", PcRemoteEnable},\r
+                       {"RemoteDisable", PcRemoteDisable},\r
+                       {"KeepEnable", PcKeepEnable},\r
+                       {"KeepDisable", PcKeepDisable},\r
+                       {"KeepSet", PcKeepSet},\r
+                       {"KeepGet", PcKeepGet},\r
+                       {"MakeCert", PtMakeCert},\r
+                       {"TrafficClient", PtTrafficClient},\r
+                       {"TrafficServer", PtTrafficServer},\r
+               };\r
+\r
+               // プロンプトの生成\r
+               StrCpy(prompt, sizeof(prompt), "VPN Client>");\r
+\r
+               if (DispatchNextCmdEx(pc->Console, pc->CmdLine, prompt, cmd, sizeof(cmd) / sizeof(cmd[0]), pc) == false)\r
+               {\r
+                       break;\r
+               }\r
+               pc->LastError = pc->Console->RetCode;\r
+\r
+               if (pc->LastError == ERR_NO_ERROR && pc->Console->ConsoleType != CONSOLE_CSV)\r
+               {\r
+                       pc->Console->Write(pc->Console, _UU("CMD_MSG_OK"));\r
+                       pc->Console->Write(pc->Console, L"");\r
+               }\r
+\r
+               if (pc->CmdLine != NULL)\r
+               {\r
+                       break;\r
+               }\r
+       }\r
+}\r
+\r
+// VPN Client サービスのバージョン情報の取得\r
+UINT PcVersionGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_VERSION t;\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       ret = CcGetClientVersion(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               CT *ct;\r
+\r
+               // 成功\r
+               ct = CtNewStandard();\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.ClientProductName);\r
+               CtInsert(ct, _UU("CMD_VersionGet_1"), tmp);\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.ClientVersionString);\r
+               CtInsert(ct, _UU("CMD_VersionGet_2"), tmp);\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.ClientBuildInfoString);\r
+               CtInsert(ct, _UU("CMD_VersionGet_3"), tmp);\r
+\r
+               UniToStru(tmp, t.ProcessId);\r
+               CtInsert(ct, _UU("CMD_VersionGet_4"), tmp);\r
+\r
+               StrToUni(tmp, sizeof(tmp), OsTypeToStr(t.OsType));\r
+               CtInsert(ct, _UU("CMD_VersionGet_5"), tmp);\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// VPN Client サービスに接続するためのパスワードの設定\r
+UINT PcPasswordSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_PASSWORD t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[password]", CmdPromptChoosePassword, NULL, NULL, NULL},\r
+               {"REMOTEONLY", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.Password, sizeof(t.Password), GetParamStr(o, "[password]"));\r
+       t.PasswordRemoteOnly = GetParamYes(o, "REMOTEONLY");\r
+\r
+       ret = CcSetPassword(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// VPN Client サービスに接続するためのパスワードの設定の取得\r
+UINT PcPasswordGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_PASSWORD_SETTING t;\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       ret = CcGetPasswordSetting(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+               CT *ct = CtNewStandard();\r
+\r
+               CtInsert(ct, _UU("CMD_PasswordGet_1"),\r
+                       t.IsPasswordPresented ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               CtInsert(ct, _UU("CMD_PasswordGet_2"),\r
+                       t.PasswordRemoteOnly ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 信頼する証明機関の証明書一覧の取得\r
+UINT PcCertList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_ENUM_CA t;\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       ret = CcEnumCa(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+               UINT i;\r
+               CT *ct = CtNewStandard();\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+                       wchar_t tmp2[64];\r
+                       RPC_CLIENT_ENUM_CA_ITEM *e = t.Items[i];\r
+\r
+                       GetDateStrEx64(tmp, sizeof(tmp), SystemToLocal64(e->Expires), NULL);\r
+\r
+                       UniToStru(tmp2, e->Key);\r
+\r
+                       CtInsert(ct, _UU("CMD_CAList_COLUMN_ID"), tmp2);\r
+                       CtInsert(ct, _UU("CM_CERT_COLUMN_1"), e->SubjectName);\r
+                       CtInsert(ct, _UU("CM_CERT_COLUMN_2"), e->IssuerName);\r
+                       CtInsert(ct, _UU("CM_CERT_COLUMN_3"), tmp);\r
+\r
+                       if (i != (t.NumItem - 1))\r
+                       {\r
+                               CtInsert(ct, L"---", L"---");\r
+                       }\r
+               }\r
+\r
+               CtFree(ct, c);\r
+\r
+               CiFreeClientEnumCa(&t);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 信頼する証明機関の証明書の追加\r
+UINT PcCertAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CERT t;\r
+       X *x;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[path]", CmdPrompt, _UU("CMD_CAAdd_PROMPT_PATH"), CmdEvalIsFile, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+\r
+       x = FileToX(GetParamStr(o, "[path]"));\r
+\r
+       if (x == NULL)\r
+       {\r
+               FreeParamValueList(o);\r
+               c->Write(c, _UU("CMD_MSG_LOAD_CERT_FAILED"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       t.x = x;\r
+\r
+       ret = CcAddCa(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       FreeX(x);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 信頼する証明機関の証明書の削除\r
+UINT PcCertDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_DELETE_CA t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[id]", CmdPrompt, _UU("CMD_CADelete_PROMPT_ID"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       t.Key = GetParamInt(o, "[id]");\r
+\r
+       ret = CcDeleteCa(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 信頼する証明機関の証明書の取得\r
+UINT PcCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_GET_CA t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[id]", CmdPrompt, _UU("CMD_CAGet_PROMPT_ID"), CmdEvalNotEmpty, NULL},\r
+               {"SAVECERT", CmdPrompt, _UU("CMD_CAGet_PROMPT_SAVECERT"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       t.Key = GetParamInt(o, "[id]");\r
+\r
+       ret = CcGetCa(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+               if (XToFile(t.x, GetParamStr(o, "SAVECERT"), true))\r
+               {\r
+                       // 成功\r
+               }\r
+               else\r
+               {\r
+                       // 失敗\r
+                       ret = ERR_INTERNAL_ERROR;\r
+                       c->Write(c, _UU("CMD_MSG_SAVE_CERT_FAILED"));\r
+               }\r
+\r
+               CiFreeGetCa(&t);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 使用できるスマートカードの種類の一覧の取得\r
+UINT PcSecureList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_ENUM_SECURE t;\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       ret = CcEnumSecure(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               CT *ct;\r
+               UINT i;\r
+               wchar_t tmp1[MAX_SIZE];\r
+               wchar_t tmp2[MAX_SIZE];\r
+               wchar_t tmp4[MAX_SIZE];\r
+               wchar_t *tmp3;\r
+\r
+               // 成功\r
+               ct = CtNew();\r
+               CtInsertColumn(ct, _UU("SEC_COLUMN1"), false);\r
+               CtInsertColumn(ct, _UU("SEC_COLUMN2"), false);\r
+               CtInsertColumn(ct, _UU("SEC_COLUMN3"), false);\r
+               CtInsertColumn(ct, _UU("SEC_COLUMN4"), false);\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       RPC_CLIENT_ENUM_SECURE_ITEM *e = t.Items[i];\r
+\r
+                       // ID\r
+                       UniToStru(tmp1, e->DeviceId);\r
+\r
+                       // デバイス名\r
+                       StrToUni(tmp2, sizeof(tmp2), e->DeviceName);\r
+\r
+                       // 種類\r
+                       tmp3 = (e->Type == SECURE_IC_CARD) ? _UU("SEC_SMART_CARD") : _UU("SEC_USB_TOKEN");\r
+\r
+                       // 製造元\r
+                       StrToUni(tmp4, sizeof(tmp4), e->Manufacturer);\r
+\r
+                       CtInsert(ct, tmp1, tmp2, tmp3, tmp4);\r
+               }\r
+\r
+               CtFreeEx(ct, c, true);\r
+\r
+               CiFreeClientEnumSecure(&t);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 使用するスマートカードの種類の選択\r
+UINT PcSecureSelect(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_USE_SECURE t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[id]", CmdPrompt, _UU("CMD_SecureSelect_PROMPT_ID"), NULL, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       t.DeviceId = GetParamInt(o, "[id]");\r
+\r
+       ret = CcUseSecure(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 使用するスマートカードの種類の ID の取得\r
+UINT PcSecureGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_USE_SECURE t;\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       ret = CcGetUseSecure(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+               wchar_t tmp[MAX_SIZE];\r
+\r
+               if (t.DeviceId != 0)\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CMD_SecureGet_Print"), t.DeviceId);\r
+               }\r
+               else\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("CMD_SecureGet_NoPrint"));\r
+               }\r
+               c->Write(c, tmp);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 新規仮想 LAN カードの作成\r
+UINT PcNicCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_CREATE_VLAN t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_NicCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "[name]"));\r
+\r
+       ret = CcCreateVLan(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 仮想 LAN カードの削除\r
+UINT PcNicDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_CREATE_VLAN t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_NicCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "[name]"));\r
+\r
+       ret = CcDeleteVLan(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 仮想 LAN カードのデバイスドライバのアップグレード\r
+UINT PcNicUpgrade(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_CREATE_VLAN t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_NicCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "[name]"));\r
+\r
+       ret = CcUpgradeVLan(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 仮想 LAN カードの設定の取得\r
+UINT PcNicGetSetting(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_VLAN t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_NicCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "[name]"));\r
+\r
+       ret = CcGetVLan(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+               CT *ct = CtNewStandard();\r
+               wchar_t tmp[MAX_SIZE];\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.DeviceName);\r
+               CtInsert(ct, _UU("CMD_NicGetSetting_1"), tmp);\r
+\r
+               CtInsert(ct, _UU("CMD_NicGetSetting_2"), t.Enabled ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.MacAddress);\r
+               CtInsert(ct, _UU("CMD_NicGetSetting_3"), tmp);\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.Version);\r
+               CtInsert(ct, _UU("CMD_NicGetSetting_4"), tmp);\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.FileName);\r
+               CtInsert(ct, _UU("CMD_NicGetSetting_5"), tmp);\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.Guid);\r
+               CtInsert(ct, _UU("CMD_NicGetSetting_6"), tmp);\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 仮想 LAN カードの設定の変更\r
+UINT PcNicSetSetting(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_SET_VLAN t;\r
+       UCHAR mac_address[6];\r
+       BUF *b;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_NicCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"MAC", CmdPrompt, _UU("CMD_NicSetSetting_PROMPT_MAC"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // MAC アドレスの検査\r
+       Zero(mac_address, sizeof(mac_address));\r
+       b = StrToBin(GetParamStr(o, "MAC"));\r
+       if (b != NULL && b->Size == 6)\r
+       {\r
+               Copy(mac_address, b->Buf, 6);\r
+       }\r
+       FreeBuf(b);\r
+\r
+       if (IsZero(mac_address, 6))\r
+       {\r
+               // MAC アドレスが不正\r
+               FreeParamValueList(o);\r
+\r
+               CmdPrintError(c, ERR_INVALID_PARAMETER);\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "[name]"));\r
+       NormalizeMacAddress(t.MacAddress, sizeof(t.MacAddress), GetParamStr(o, "MAC"));\r
+\r
+       ret = CcSetVLan(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 仮想 LAN カードの有効化\r
+UINT PcNicEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_CREATE_VLAN t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_NicCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "[name]"));\r
+\r
+       ret = CcEnableVLan(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 仮想 LAN カードの無効化\r
+UINT PcNicDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_CREATE_VLAN t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_NicCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "[name]"));\r
+\r
+       ret = CcDisableVLan(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 仮想 LAN カード一覧の取得\r
+UINT PcNicList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_ENUM_VLAN t;\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       ret = CcEnumVLan(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               CT *ct;\r
+               UINT i;\r
+\r
+               // 成功\r
+               ct = CtNew();\r
+               CtInsertColumn(ct, _UU("CM_VLAN_COLUMN_1"), false);\r
+               CtInsertColumn(ct, _UU("CM_VLAN_COLUMN_2"), false);\r
+               CtInsertColumn(ct, _UU("CM_VLAN_COLUMN_3"), false);\r
+               CtInsertColumn(ct, _UU("CM_VLAN_COLUMN_4"), false);\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       wchar_t name[MAX_SIZE];\r
+                       wchar_t mac[MAX_SIZE];\r
+                       wchar_t ver[MAX_SIZE];\r
+                       wchar_t *status;\r
+                       RPC_CLIENT_ENUM_VLAN_ITEM *v = t.Items[i];\r
+\r
+                       // デバイス名\r
+                       StrToUni(name, sizeof(name), v->DeviceName);\r
+\r
+                       // 状態\r
+                       status = v->Enabled ? _UU("CM_VLAN_ENABLED") : _UU("CM_VLAN_DISABLED");\r
+\r
+                       // MAC アドレス\r
+                       StrToUni(mac, sizeof(mac), v->MacAddress);\r
+\r
+                       // バージョン\r
+                       StrToUni(ver, sizeof(ver), v->Version);\r
+\r
+                       CtInsert(ct,\r
+                               name, status, mac, ver);\r
+               }\r
+\r
+               CtFreeEx(ct, c, true);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientEnumVLan(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// プロトコル名文字列を取得\r
+wchar_t *GetProtocolName(UINT n)\r
+{\r
+       switch (n)\r
+       {\r
+       case PROXY_DIRECT:\r
+               return _UU("PROTO_DIRECT_TCP");\r
+       case PROXY_HTTP:\r
+               return _UU("PROTO_HTTP_PROXY");\r
+       case PROXY_SOCKS:\r
+               return _UU("PROTO_SOCKS_PROXY");\r
+       }\r
+\r
+       return _UU("PROTO_UNKNOWN");\r
+}\r
+\r
+// 接続設定一覧の取得\r
+UINT PcAccountList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_ENUM_ACCOUNT t;\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       ret = CcEnumAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               UINT i;\r
+               CT *ct;\r
+\r
+               // 成功\r
+               ct = CtNew();\r
+               CtInsertColumn(ct, _UU("CM_ACCOUNT_COLUMN_1"), false);\r
+               CtInsertColumn(ct, _UU("CM_ACCOUNT_COLUMN_2"), false);\r
+               CtInsertColumn(ct, _UU("CM_ACCOUNT_COLUMN_3"), false);\r
+               CtInsertColumn(ct, _UU("CM_ACCOUNT_COLUMN_3_2"), false);\r
+               CtInsertColumn(ct, _UU("CM_ACCOUNT_COLUMN_4"), false);\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       RPC_CLIENT_ENUM_ACCOUNT_ITEM *e = t.Items[i];\r
+                       wchar_t tmp[MAX_SIZE];\r
+                       wchar_t tmp2[MAX_SIZE];\r
+                       wchar_t tmp4[MAX_SIZE];\r
+                       IP ip;\r
+                       char ip_str[MAX_SIZE];\r
+\r
+                       // IPv6 アドレスの場合の特別処理\r
+                       if (StrToIP6(&ip, e->ServerName) && StartWith(e->ServerName, "[") == false)\r
+                       {\r
+                               Format(ip_str, sizeof(ip_str),\r
+                                       "[%s]", e->ServerName);\r
+                       }\r
+                       else\r
+                       {\r
+                               StrCpy(ip_str, sizeof(ip_str), e->ServerName);\r
+                       }\r
+\r
+                       if (e->Port == 0)\r
+                       {\r
+                               // ポート番号不明\r
+                               UniFormat(tmp2, sizeof(tmp2), L"%S (%s)", ip_str, GetProtocolName(e->ProxyType));\r
+                       }\r
+                       else\r
+                       {\r
+                               // ポート番号併記\r
+                               UniFormat(tmp2, sizeof(tmp2), L"%S:%u (%s)", ip_str, e->Port, GetProtocolName(e->ProxyType));\r
+                       }\r
+\r
+                       // 仮想 HUB 名\r
+                       StrToUni(tmp4, sizeof(tmp4), e->HubName);\r
+\r
+                       // 追加\r
+                       StrToUni(tmp, sizeof(tmp), e->DeviceName);\r
+\r
+                       CtInsert(ct,\r
+                               e->AccountName,\r
+                               e->Active == false ? _UU("CM_ACCOUNT_OFFLINE") :\r
+                               (e->Connected ? _UU("CM_ACCOUNT_ONLINE") : _UU("CM_ACCOUNT_CONNECTING")),\r
+                               tmp2, tmp4,\r
+                               tmp);\r
+               }\r
+\r
+               CtFreeEx(ct, c, true);\r
+       }\r
+\r
+       CiFreeClientEnumAccount(&t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 新しい接続設定の作成\r
+UINT PcAccountCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_CREATE_ACCOUNT t;\r
+       UINT port = 443;\r
+       char *host = NULL;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"SERVER", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Server"), CmdEvalHostAndPort, NULL},\r
+               {"HUB", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Hub"), CmdEvalSafe, NULL},\r
+               {"USERNAME", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Username"), CmdEvalNotEmpty, NULL},\r
+               {"NICNAME", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Nicname"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 443);\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+       t.ClientOption->Port = port;\r
+       StrCpy(t.ClientOption->Hostname, sizeof(t.ClientOption->Hostname), host);\r
+       StrCpy(t.ClientOption->HubName, sizeof(t.ClientOption->HubName), GetParamStr(o, "HUB"));\r
+       t.ClientOption->NumRetry = INFINITE;\r
+       t.ClientOption->RetryInterval = 15;\r
+       t.ClientOption->MaxConnection = 1;\r
+       t.ClientOption->UseEncrypt = true;\r
+       t.ClientOption->AdditionalConnectionInterval = 1;\r
+       StrCpy(t.ClientOption->DeviceName, sizeof(t.ClientOption->DeviceName), GetParamStr(o, "NICNAME"));\r
+\r
+       t.ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));\r
+       t.ClientAuth->AuthType = CLIENT_AUTHTYPE_ANONYMOUS;\r
+       StrCpy(t.ClientAuth->Username, sizeof(t.ClientAuth->Username), GetParamStr(o, "USERNAME"));\r
+\r
+       Free(host);\r
+\r
+       ret = CcCreateAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       CiFreeClientCreateAccount(&t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定の接続先の設定\r
+UINT PcAccountSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       char *host = NULL;\r
+       UINT port = 443;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"SERVER", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Server"), CmdEvalHostAndPort, NULL},\r
+               {"HUB", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Hub"), CmdEvalSafe, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 443);\r
+\r
+       Zero(&t, sizeof(t));\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT c;\r
+               // 成功\r
+               t.ClientOption->Port = port;\r
+               StrCpy(t.ClientOption->Hostname, sizeof(t.ClientOption->Hostname), host);\r
+               StrCpy(t.ClientOption->HubName, sizeof(t.ClientOption->HubName), GetParamStr(o, "HUB"));\r
+\r
+               Zero(&c, sizeof(c));\r
+\r
+               c.ClientAuth = t.ClientAuth;\r
+               c.ClientOption = t.ClientOption;\r
+               c.CheckServerCert = t.CheckServerCert;\r
+               c.ServerCert = t.ServerCert;\r
+               c.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &c);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       Free(host);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定の設定の取得\r
+UINT PcAccountGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 接続設定の内容を表示\r
+               wchar_t tmp[MAX_SIZE];\r
+\r
+               CT *ct = CtNewStandard();\r
+\r
+               // 接続設定名\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_NAME"), t.ClientOption->AccountName);\r
+\r
+               // 接続先 VPN Server のホスト名\r
+               StrToUni(tmp, sizeof(tmp), t.ClientOption->Hostname);\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_HOSTNAME"), tmp);\r
+\r
+               // 接続先 VPN Server のポート番号\r
+               UniToStru(tmp, t.ClientOption->Port);\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PORT"), tmp);\r
+\r
+               // 接続先 VPN Server の仮想 HUB 名\r
+               StrToUni(tmp, sizeof(tmp), t.ClientOption->HubName);\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_HUBNAME"), tmp);\r
+\r
+               // 経由するプロキシ サーバーの種類\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_TYPE"), GetProxyTypeStr(t.ClientOption->ProxyType));\r
+\r
+               if (t.ClientOption->ProxyType != PROXY_DIRECT)\r
+               {\r
+                       // プロキシ サーバーのホスト名\r
+                       StrToUni(tmp, sizeof(tmp), t.ClientOption->ProxyName);\r
+                       CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_HOSTNAME"), tmp);\r
+\r
+                       // プロキシ サーバーのポート番号\r
+                       UniToStru(tmp, t.ClientOption->ProxyPort);\r
+                       CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_PORT"), tmp);\r
+\r
+                       // プロキシ サーバーのユーザー名\r
+                       StrToUni(tmp, sizeof(tmp), t.ClientOption->ProxyUsername);\r
+                       CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_USERNAME"), tmp);\r
+               }\r
+\r
+               // サーバー証明書の検証\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_SERVER_CERT_USE"),\r
+                       t.CheckServerCert ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               // 登録されている固有証明書\r
+               if (t.ServerCert != NULL)\r
+               {\r
+                       GetAllNameFromX(tmp, sizeof(tmp), t.ServerCert);\r
+                       CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_SERVER_CERT_NAME"), tmp);\r
+               }\r
+\r
+               // 接続に使用するデバイス名\r
+               StrToUni(tmp, sizeof(tmp), t.ClientOption->DeviceName);\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_DEVICE_NAME"), tmp);\r
+\r
+               // 認証の種類\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_AUTH_TYPE"), GetClientAuthTypeStr(t.ClientAuth->AuthType));\r
+\r
+               // ユーザー名\r
+               StrToUni(tmp, sizeof(tmp), t.ClientAuth->Username);\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_AUTH_USERNAME"), tmp);\r
+\r
+               if (t.ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)\r
+               {\r
+                       if (t.ClientAuth->ClientX != NULL)\r
+                       {\r
+                               // クライアント証明書名\r
+                               GetAllNameFromX(tmp, sizeof(tmp), t.ClientAuth->ClientX);\r
+                               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_AUTH_CERT_NAME"), tmp);\r
+                       }\r
+               }\r
+\r
+               // VPN 通信に使用する TCP コネクション数\r
+               UniToStru(tmp, t.ClientOption->MaxConnection);\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_NUMTCP"), tmp);\r
+\r
+               // 各 TCP コネクションの確立間隔\r
+               UniToStru(tmp, t.ClientOption->AdditionalConnectionInterval);\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_TCP_INTERVAL"), tmp);\r
+\r
+               // 各 TCP コネクションの寿命\r
+               if (t.ClientOption->ConnectionDisconnectSpan != 0)\r
+               {\r
+                       UniToStru(tmp, t.ClientOption->ConnectionDisconnectSpan);\r
+               }\r
+               else\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("CMD_MSG_INFINITE"));\r
+               }\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_TCP_TTL"), tmp);\r
+\r
+               // 半二重モードの使用\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_TCP_HALF"),\r
+                       t.ClientOption->HalfConnection ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               // SSL による暗号化\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_ENCRYPT"),\r
+                       t.ClientOption->UseEncrypt ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               // データ圧縮\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_COMPRESS"),\r
+                       t.ClientOption->UseCompress ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               // ブリッジ / ルータモードで接続\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_BRIDGE_ROUTER"),\r
+                       t.ClientOption->RequireBridgeRoutingMode ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               // モニタリングモードで接続\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_MONITOR"),\r
+                       t.ClientOption->RequireMonitorMode ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               // ルーティング テーブルを書き換えない\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_NO_TRACKING"),\r
+                       t.ClientOption->NoRoutingTracking ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               // QoS制御を無効化する\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_QOS_DISABLE"),\r
+                       t.ClientOption->DisableQoS ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定の削除\r
+UINT PcAccountDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_DELETE_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcDeleteAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定の接続に使用するユーザー名の設定\r
+UINT PcAccountUsernameSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"USERNAME", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Username"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               StrCpy(t.ClientAuth->Username, sizeof(t.ClientAuth->Username), GetParamStr(o, "USERNAME"));\r
+\r
+               if (t.ClientAuth->AuthType == CLIENT_AUTHTYPE_PASSWORD)\r
+               {\r
+                       c->Write(c, _UU("CMD_AccountUsername_Notice"));\r
+               }\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定のユーザー認証の種類を匿名認証に設定\r
+UINT PcAccountAnonymousSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               t.ClientAuth->AuthType = CLIENT_AUTHTYPE_ANONYMOUS;\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定のユーザー認証の種類をパスワード認証に設定\r
+UINT PcAccountPasswordSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"PASSWORD", CmdPromptChoosePassword, NULL, NULL, NULL},\r
+               {"TYPE", CmdPrompt, _UU("CMD_CascadePasswordSet_Prompt_Type"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               char *typestr = GetParamStr(o, "TYPE");\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+\r
+               // 設定変更\r
+               if (StartWith("standard", typestr))\r
+               {\r
+                       t.ClientAuth->AuthType = CLIENT_AUTHTYPE_PASSWORD;\r
+                       HashPassword(t.ClientAuth->HashedPassword, t.ClientAuth->Username,\r
+                               GetParamStr(o, "PASSWORD"));\r
+               }\r
+               else if (StartWith("radius", typestr) || StartWith("ntdomain", typestr))\r
+               {\r
+                       t.ClientAuth->AuthType = CLIENT_AUTHTYPE_PLAIN_PASSWORD;\r
+\r
+                       StrCpy(t.ClientAuth->PlainPassword, sizeof(t.ClientAuth->PlainPassword),\r
+                               GetParamStr(o, "PASSWORD"));\r
+               }\r
+               else\r
+               {\r
+                       // エラー発生\r
+                       c->Write(c, _UU("CMD_CascadePasswordSet_Type_Invalid"));\r
+                       ret = ERR_INVALID_PARAMETER;\r
+               }\r
+\r
+               if (ret == ERR_NO_ERROR)\r
+               {\r
+                       Zero(&z, sizeof(z));\r
+                       z.CheckServerCert = t.CheckServerCert;\r
+                       z.ClientAuth = t.ClientAuth;\r
+                       z.ClientOption = t.ClientOption;\r
+                       z.ServerCert = t.ServerCert;\r
+                       z.StartupAccount = t.StartupAccount;\r
+\r
+                       ret = CcSetAccount(pc->RemoteClient, &z);\r
+               }\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定のユーザー認証の種類をクライアント証明書認証に設定\r
+UINT PcAccountCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       X *x;\r
+       K *k;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"LOADCERT", CmdPrompt, _UU("CMD_LOADCERTPATH"), CmdEvalIsFile, NULL},\r
+               {"LOADKEY", CmdPrompt, _UU("CMD_LOADKEYPATH"), CmdEvalIsFile, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (CmdLoadCertAndKey(c, &x, &k, GetParamStr(o, "LOADCERT"), GetParamStr(o, "LOADKEY")) == false)\r
+       {\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+\r
+               t.ClientAuth->AuthType = CLIENT_AUTHTYPE_CERT;\r
+               if (t.ClientAuth->ClientX != NULL)\r
+               {\r
+                       FreeX(t.ClientAuth->ClientX);\r
+               }\r
+               if (t.ClientAuth->ClientK != NULL)\r
+               {\r
+                       FreeK(t.ClientAuth->ClientK);\r
+               }\r
+\r
+               t.ClientAuth->ClientX = CloneX(x);\r
+               t.ClientAuth->ClientK = CloneK(k);\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       FreeX(x);\r
+       FreeK(k);\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定に用いるクライアント証明書の取得\r
+UINT PcAccountCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"SAVECERT", CmdPrompt, _UU("CMD_SAVECERTPATH"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               if (t.ClientAuth->AuthType != CLIENT_AUTHTYPE_CERT)\r
+               {\r
+                       c->Write(c, _UU("CMD_CascadeCertSet_Not_Auth_Cert"));\r
+                       ret = ERR_INTERNAL_ERROR;\r
+               }\r
+               else if (t.ClientAuth->ClientX == NULL)\r
+               {\r
+                       c->Write(c, _UU("CMD_CascadeCertSet_Cert_Not_Exists"));\r
+                       ret = ERR_INTERNAL_ERROR;\r
+               }\r
+               else\r
+               {\r
+                       XToFile(t.ClientAuth->ClientX, GetParamStr(o, "SAVECERT"), true);\r
+               }\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定の通信時の暗号化の無効化\r
+UINT PcAccountEncryptDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               t.ClientOption->UseEncrypt = false;\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定の通信時の暗号化の有効化\r
+UINT PcAccountEncryptEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               t.ClientOption->UseEncrypt = true;\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定の通信時のデータ圧縮の有効化\r
+UINT PcAccountCompressEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               t.ClientOption->UseCompress = true;\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定の通信時のデータ圧縮の無効化\r
+UINT PcAccountCompressDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               t.ClientOption->UseCompress = false;\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定の接続方法を直接 TCP/IP 接続に設定\r
+UINT PcAccountProxyNone(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               t.ClientOption->ProxyType = PROXY_DIRECT;\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定の接続方法を HTTP プロキシサーバー経由接続に設定\r
+UINT PcAccountProxyHttp(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"SERVER", CmdPrompt, _UU("CMD_AccountProxyHttp_Prompt_Server"), CmdEvalHostAndPort, NULL},\r
+               {"USERNAME", NULL, NULL, NULL, NULL},\r
+               {"PASSWORD", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               char *host;\r
+               UINT port;\r
+\r
+               // データ変更\r
+               if (ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 8080))\r
+               {\r
+                       t.ClientOption->ProxyType = PROXY_HTTP;\r
+                       StrCpy(t.ClientOption->ProxyName, sizeof(t.ClientOption->ProxyName), host);\r
+                       t.ClientOption->ProxyPort = port;\r
+                       StrCpy(t.ClientOption->ProxyUsername, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "USERNAME"));\r
+                       StrCpy(t.ClientOption->ProxyPassword, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "PASSWORD"));\r
+                       Free(host);\r
+               }\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定の接続方法を SOCKS プロキシサーバー経由接続に設定\r
+UINT PcAccountProxySocks(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"SERVER", CmdPrompt, _UU("CMD_AccountProxyHttp_Prompt_Server"), CmdEvalHostAndPort, NULL},\r
+               {"USERNAME", NULL, NULL, NULL, NULL},\r
+               {"PASSWORD", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               char *host;\r
+               UINT port;\r
+\r
+               // データ変更\r
+               if (ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 8080))\r
+               {\r
+                       t.ClientOption->ProxyType = PROXY_SOCKS;\r
+                       StrCpy(t.ClientOption->ProxyName, sizeof(t.ClientOption->ProxyName), host);\r
+                       t.ClientOption->ProxyPort = port;\r
+                       StrCpy(t.ClientOption->ProxyUsername, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "USERNAME"));\r
+                       StrCpy(t.ClientOption->ProxyPassword, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "PASSWORD"));\r
+                       Free(host);\r
+               }\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定のサーバー証明書の検証オプションの有効化\r
+UINT PcAccountServerCertEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               t.CheckServerCert = true;\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定のサーバー証明書の検証オプションの無効化\r
+UINT PcAccountServerCertDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               t.CheckServerCert = false;\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定のサーバー固有証明書の設定\r
+UINT PcAccountServerCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       X *x;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"LOADCERT", CmdPrompt, _UU("CMD_LOADCERTPATH"), CmdEvalIsFile, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       x = FileToX(GetParamStr(o, "LOADCERT"));\r
+       if (x == NULL)\r
+       {\r
+               FreeParamValueList(o);\r
+               c->Write(c, _UU("CMD_LOADCERT_FAILED"));\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               if (t.ServerCert != NULL)\r
+               {\r
+                       FreeX(t.ServerCert);\r
+               }\r
+               t.ServerCert = CloneX(x);\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       FreeX(x);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定のサーバー固有証明書の削除\r
+UINT PcAccountServerCertDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               if (t.ServerCert != NULL)\r
+               {\r
+                       FreeX(t.ServerCert);\r
+               }\r
+               t.ServerCert = NULL;\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定のサーバー固有証明書の取得\r
+UINT PcAccountServerCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"SAVECERT", CmdPrompt, _UU("CMD_SAVECERTPATH"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               if (t.ServerCert != NULL)\r
+               {\r
+                       FreeX(t.ServerCert);\r
+               }\r
+               t.ServerCert = NULL;\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定の高度な通信設定の設定\r
+UINT PcAccountDetailSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       CMD_EVAL_MIN_MAX mm_maxtcp =\r
+       {\r
+               "CMD_CascadeDetailSet_Eval_MaxTcp", 1, 32\r
+       };\r
+       CMD_EVAL_MIN_MAX mm_interval =\r
+       {\r
+               "CMD_CascadeDetailSet_Eval_Interval", 1, 4294967295UL\r
+       };\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"MAXTCP", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_MaxTcp"), CmdEvalMinMax, &mm_maxtcp},\r
+               {"INTERVAL", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_Interval"), CmdEvalMinMax, &mm_interval},\r
+               {"TTL", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_TTL"), NULL, NULL},\r
+               {"HALF", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_HALF"), NULL, NULL},\r
+               {"BRIDGE", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_BRIDGE"), NULL, NULL},\r
+               {"MONITOR", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_MONITOR"), NULL, NULL},\r
+               {"NOTRACK", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_NOTRACK"), NULL, NULL},\r
+               {"NOQOS", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_NOQOS"), NULL, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // データ変更\r
+               t.ClientOption->MaxConnection = GetParamInt(o, "MAXTCP");\r
+               t.ClientOption->AdditionalConnectionInterval = GetParamInt(o, "INTERVAL");\r
+               t.ClientOption->ConnectionDisconnectSpan = GetParamInt(o, "TTL");\r
+               t.ClientOption->HalfConnection = GetParamYes(o, "HALF");\r
+               t.ClientOption->RequireBridgeRoutingMode = GetParamYes(o, "BRIDGE");\r
+               t.ClientOption->RequireMonitorMode = GetParamYes(o, "MONITOR");\r
+               t.ClientOption->NoRoutingTracking = GetParamYes(o, "NOTRACK");\r
+               t.ClientOption->DisableQoS = GetParamYes(o, "NOQOS");\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定の名前の変更\r
+UINT PcAccountRename(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_RENAME_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountRename_PROMPT_OLD"), CmdEvalNotEmpty, NULL},\r
+               {"NEW", CmdPrompt, _UU("CMD_AccountRename_PROMPT_NEW"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       UniStrCpy(t.NewName, sizeof(t.NewName), GetParamUniStr(o, "NEW"));\r
+       UniStrCpy(t.OldName, sizeof(t.OldName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcRenameAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定を使用して VPN Server へ接続を開始\r
+UINT PcAccountConnect(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_CONNECT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcConnect(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続中の接続設定の切断\r
+UINT PcAccountDisconnect(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_CONNECT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcDisconnect(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定の現在の状態の取得\r
+UINT PcAccountStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_CONNECTION_STATUS t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccountStatus(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               if (t.Active == false)\r
+               {\r
+                       // 切断されている\r
+                       ret = ERR_ACCOUNT_INACTIVE;\r
+               }\r
+               else\r
+               {\r
+                       CT *ct = CtNewStandard();\r
+\r
+                       CmdPrintStatusToListView(ct, &t);\r
+\r
+                       CtFree(ct, c);\r
+               }\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetConnectionStatus(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定で使用する仮想 LAN カードの設定\r
+UINT PcAccountNicSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"NICNAME", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Nicname"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       Zero(&t, sizeof(t));\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT c;\r
+               // 成功\r
+               StrCpy(t.ClientOption->DeviceName, sizeof(t.ClientOption->DeviceName),\r
+                       GetParamStr(o, "NICNAME"));\r
+\r
+               Zero(&c, sizeof(c));\r
+\r
+               c.ClientAuth = t.ClientAuth;\r
+               c.ClientOption = t.ClientOption;\r
+               c.CheckServerCert = t.CheckServerCert;\r
+               c.ServerCert = t.ServerCert;\r
+               c.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &c);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// VPN Server への接続中に接続状況やエラー画面を表示するように設定\r
+UINT PcAccountStatusShow(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               t.ClientOption->HideStatusWindow = false;\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// VPN Server への接続中に接続状況やエラー画面を表示しないように設定\r
+UINT PcAccountStatusHide(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               t.ClientOption->HideStatusWindow = true;\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定のユーザー認証の種類をスマートカード認証に設定\r
+UINT PcAccountSecureCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"CERTNAME", CmdPrompt, _UU("CMD_AccountSecureCertSet_PROMPT_CERTNAME"), CmdEvalNotEmpty, NULL},\r
+               {"KEYNAME", CmdPrompt, _UU("CMD_AccountSecureCertSet_PROMPT_KEYNAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               t.ClientAuth->AuthType = CLIENT_AUTHTYPE_SECURE;\r
+               StrCpy(t.ClientAuth->SecurePublicCertName, sizeof(t.ClientAuth->SecurePublicCertName),\r
+                       GetParamStr(o, "CERTNAME"));\r
+               StrCpy(t.ClientAuth->SecurePrivateKeyName, sizeof(t.ClientAuth->SecurePrivateKeyName),\r
+                       GetParamStr(o, "KEYNAME"));\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定の接続失敗または切断時の再試行回数と間隔の設定\r
+UINT PcAccountRetrySet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       CMD_EVAL_MIN_MAX minmax =\r
+       {\r
+               "CMD_AccountRetrySet_EVAL_INTERVAL",\r
+               5,\r
+               4294967295UL,\r
+       };\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"NUM", CmdPrompt, _UU("CMD_AccountRetrySet_PROMPT_NUM"), CmdEvalNotEmpty, NULL},\r
+               {"INTERVAL", CmdPrompt, _UU("CMD_AccountRetrySet_PROMPY_INTERVAL"), CmdEvalMinMax, &minmax},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               UINT num = GetParamInt(o, "NUM");\r
+               UINT interval = GetParamInt(o, "INTERVAL");\r
+\r
+               t.ClientOption->NumRetry = (num == 999) ? INFINITE : num;\r
+               t.ClientOption->RetryInterval = interval;\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+\r
+// 接続設定をスタートアップ接続に設定\r
+UINT PcAccountStartupSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               t.StartupAccount = true;\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定のスタートアップ接続を解除\r
+UINT PcAccountStartupRemove(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               // 設定変更\r
+               t.StartupAccount = false;\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               ret = CcSetAccount(pc->RemoteClient, &z);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 接続設定のエクスポート\r
+UINT PcAccountExport(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       RPC_CLIENT_GET_ACCOUNT t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"SAVEPATH", CmdPrompt, _UU("CMD_AccountExport_PROMPT_SAVEPATH"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = CcGetAccount(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT z;\r
+               BUF *b;\r
+               BUF *b2;\r
+               char tmp[MAX_SIZE];\r
+               UCHAR *buf;\r
+               UINT buf_size;\r
+               UCHAR bom[] = {0xef, 0xbb, 0xbf, };\r
+\r
+               Zero(&z, sizeof(z));\r
+               z.CheckServerCert = t.CheckServerCert;\r
+               z.ClientAuth = t.ClientAuth;\r
+               z.ClientOption = t.ClientOption;\r
+               z.ServerCert = t.ServerCert;\r
+               z.StartupAccount = t.StartupAccount;\r
+\r
+               b = CiAccountToCfg(&z);\r
+\r
+               StrCpy(tmp, sizeof(tmp), GetParamStr(o, "SAVEPATH"));\r
+               b2 = NewBuf();\r
+\r
+               WriteBuf(b2, bom, sizeof(bom));\r
+\r
+               // ヘッダ部分を付加する\r
+               buf_size = CalcUniToUtf8(_UU("CM_ACCOUNT_FILE_BANNER"));\r
+               buf = ZeroMalloc(buf_size + 32);\r
+               UniToUtf8(buf, buf_size, _UU("CM_ACCOUNT_FILE_BANNER"));\r
+\r
+               WriteBuf(b2, buf, StrLen((char *)buf));\r
+               WriteBuf(b2, b->Buf, b->Size);\r
+               SeekBuf(b2, 0, 0);\r
+\r
+               FreeBuf(b);\r
+\r
+               if (DumpBuf(b2, tmp) == false)\r
+               {\r
+                       c->Write(c, _UU("CMD_SAVEFILE_FAILED"));\r
+                       ret = ERR_INTERNAL_ERROR;\r
+               }\r
+\r
+               FreeBuf(b2);\r
+               Free(buf);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       CiFreeClientGetAccount(&t);\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 指定されたアカウント名が存在するかチェックする\r
+bool CmdIsAccountName(REMOTE_CLIENT *r, wchar_t *name)\r
+{\r
+       UINT i;\r
+       RPC_CLIENT_ENUM_ACCOUNT t;\r
+       wchar_t tmp[MAX_SIZE];\r
+       bool b = false;\r
+       // 引数チェック\r
+       if (r == NULL || name == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (CcEnumAccount(r, &t) != ERR_NO_ERROR)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       UniStrCpy(tmp, sizeof(tmp), name);\r
+       UniTrim(tmp);\r
+\r
+       for (i = 0;i < t.NumItem;i++)\r
+       {\r
+               if (UniStrCmpi(t.Items[i]->AccountName, tmp) == 0)\r
+               {\r
+                       b = true;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       CiFreeClientEnumAccount(&t);\r
+\r
+       return b;\r
+}\r
+\r
+// インポート名の生成\r
+void CmdGenerateImportName(REMOTE_CLIENT *r, wchar_t *name, UINT size, wchar_t *old_name)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (r == NULL || name == NULL || old_name == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       for (i = 1;;i++)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               if (i == 1)\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_IMPORT_NAME_1"), old_name);\r
+               }\r
+               else\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_IMPORT_NAME_2"), old_name, i);\r
+               }\r
+\r
+               if (CmdIsAccountName(r, tmp) == false)\r
+               {\r
+                       UniStrCpy(name, size, tmp);\r
+                       return;\r
+               }\r
+       }\r
+}\r
+\r
+// 接続設定のインポート\r
+UINT PcAccountImport(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       BUF *b;\r
+       wchar_t name[MAX_SIZE];\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[path]", CmdPrompt, _UU("CMD_AccountImport_PROMPT_PATH"), CmdEvalIsFile, NULL},\r
+       };\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // ファイルを読み込む\r
+       b = ReadDump(GetParamStr(o, "[path]"));\r
+\r
+       if (b == NULL)\r
+       {\r
+               // 読み込み失敗\r
+               c->Write(c, _UU("CMD_LOADFILE_FAILED"));\r
+               ret = ERR_INTERNAL_ERROR;\r
+       }\r
+       else\r
+       {\r
+               RPC_CLIENT_CREATE_ACCOUNT *t;\r
+\r
+               t = CiCfgToAccount(b);\r
+\r
+               if (t == NULL)\r
+               {\r
+                       // パースに失敗\r
+                       c->Write(c, _UU("CMD_AccountImport_FAILED_PARSE"));\r
+                       ret = ERR_INTERNAL_ERROR;\r
+               }\r
+               else\r
+               {\r
+                       CmdGenerateImportName(pc->RemoteClient, name, sizeof(name), t->ClientOption->AccountName);\r
+                       UniStrCpy(t->ClientOption->AccountName, sizeof(t->ClientOption->AccountName), name);\r
+\r
+                       ret = CcCreateAccount(pc->RemoteClient, t);\r
+\r
+                       if (ret == ERR_NO_ERROR)\r
+                       {\r
+                               wchar_t tmp[MAX_SIZE];\r
+\r
+                               UniFormat(tmp, sizeof(tmp), _UU("CMD_AccountImport_OK"), name);\r
+                               c->Write(c, tmp);\r
+                       }\r
+\r
+                       CiFreeClientCreateAccount(t);\r
+                       Free(t);\r
+               }\r
+\r
+               FreeBuf(b);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// VPN Client サービスのリモート管理の許可\r
+UINT PcRemoteEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       CLIENT_CONFIG t;\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       ret = CcGetClientConfig(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               t.AllowRemoteConfig = true;\r
+               ret = CcSetClientConfig(pc->RemoteClient, &t);\r
+       }\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// VPN Client サービスのリモート管理の禁止\r
+UINT PcRemoteDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       CLIENT_CONFIG t;\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       ret = CcGetClientConfig(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               t.AllowRemoteConfig = false;\r
+               ret = CcSetClientConfig(pc->RemoteClient, &t);\r
+       }\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// インターネット接続の維持機能の有効化\r
+UINT PcKeepEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       CLIENT_CONFIG t;\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       ret = CcGetClientConfig(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 設定変更\r
+               t.UseKeepConnect = true;\r
+               ret = CcSetClientConfig(pc->RemoteClient, &t);\r
+       }\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// インターネット接続の維持機能の無効化\r
+UINT PcKeepDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       CLIENT_CONFIG t;\r
+\r
+       // パラメータリストの取得\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       ret = CcGetClientConfig(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 設定変更\r
+               t.UseKeepConnect = false;\r
+               ret = CcSetClientConfig(pc->RemoteClient, &t);\r
+       }\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               // 成功\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// インターネット接続の維持機能の設定\r
+UINT PcKeepSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       CLIENT_CONFIG t;\r
+       char *host;\r
+       UINT port;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"HOST", CmdPrompt, _UU("CMD_KeepSet_PROMPT_HOST"), CmdEvalHostAndPort, NULL},\r
+               {"PROTOCOL", CmdPrompt, _UU("CMD_KeepSet_PROMPT_PROTOCOL"), CmdEvalTcpOrUdp, NULL},\r
+               {"INTERVAL", CmdPrompt, _UU("CMD_KeepSet_PROMPT_INTERVAL"), NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       ret = CcGetClientConfig(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               if (ParseHostPort(GetParamStr(o, "HOST"), &host, &port, 0))\r
+               {\r
+                       StrCpy(t.KeepConnectHost, sizeof(t.KeepConnectHost), host);\r
+                       t.KeepConnectPort = port;\r
+                       t.KeepConnectInterval = GetParamInt(o, "INTERVAL");\r
+                       t.KeepConnectProtocol = (StrCmpi(GetParamStr(o, "PROTOCOL"), "tcp") == 0) ? 0 : 1;\r
+                       Free(host);\r
+\r
+                       ret = CcSetClientConfig(pc->RemoteClient, &t);\r
+               }\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// インターネット接続の維持機能の取得\r
+UINT PcKeepGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PC *pc = (PC *)param;\r
+       UINT ret = ERR_NO_ERROR;\r
+       CLIENT_CONFIG t;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       Zero(&t, sizeof(t));\r
+\r
+       ret = CcGetClientConfig(pc->RemoteClient, &t);\r
+\r
+       if (ret == ERR_NO_ERROR)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               CT *ct = CtNewStandard();\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.KeepConnectHost);\r
+               CtInsert(ct, _UU("CMD_KeepGet_COLUMN_1"), tmp);\r
+\r
+               UniToStru(tmp, t.KeepConnectPort);\r
+               CtInsert(ct, _UU("CMD_KeepGet_COLUMN_2"), tmp);\r
+\r
+               UniToStru(tmp, t.KeepConnectInterval);\r
+               CtInsert(ct, _UU("CMD_KeepGet_COLUMN_3"), tmp);\r
+\r
+               CtInsert(ct, _UU("CMD_KeepGet_COLUMN_4"),\r
+                       t.KeepConnectProtocol == 0 ? L"TCP/IP" : L"UDP/IP");\r
+\r
+               CtInsert(ct, _UU("CMD_KeepGet_COLUMN_5"),\r
+                       t.UseKeepConnect ? _UU("SM_ACCESS_ENABLE") : _UU("SM_ACCESS_DISABLE"));\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラーが発生した\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       // パラメータリストの解放\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+\r
+// 新しいクライアント管理ツールコンテキストの作成\r
+PC *NewPc(CONSOLE *c, REMOTE_CLIENT *remote_client, char *servername, wchar_t *cmdline)\r
+{\r
+       PC *pc;\r
+       // 引数チェック\r
+       if (c == NULL || remote_client == NULL || servername == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+       if (UniIsEmptyStr(cmdline))\r
+       {\r
+               cmdline = NULL;\r
+       }\r
+\r
+       pc = ZeroMalloc(sizeof(PC));\r
+       pc->ConsoleForServer = false;\r
+       pc->ServerName = CopyStr(servername);\r
+       pc->Console = c;\r
+       pc->LastError = 0;\r
+       pc->RemoteClient = remote_client;\r
+       pc->CmdLine = CopyUniStr(cmdline);\r
+\r
+       return pc;\r
+}\r
+\r
+// クライアント管理ツールコンテキストの解放\r
+void FreePc(PC *pc)\r
+{\r
+       // 引数チェック\r
+       if (pc == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(pc->ServerName);\r
+       Free(pc->CmdLine);\r
+       Free(pc);\r
+}\r
+\r
+// クライアント管理ツール\r
+UINT PcConnect(CONSOLE *c, char *target, wchar_t *cmdline, char *password)\r
+{\r
+       CEDAR *cedar;\r
+       REMOTE_CLIENT *client;\r
+       bool bad_pass;\r
+       bool no_remote;\r
+       char pass[MAX_SIZE];\r
+       UINT ret = 0;\r
+       // 引数チェック\r
+       if (c == NULL || target == NULL)\r
+       {\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       StrCpy(pass, sizeof(pass), password);\r
+\r
+       cedar = NewCedar(NULL, NULL);\r
+\r
+RETRY:\r
+       client = CcConnectRpc(target, pass, &bad_pass, &no_remote, 0);\r
+\r
+       if (client == NULL)\r
+       {\r
+               if (no_remote)\r
+               {\r
+                       // リモート接続拒否\r
+                       c->Write(c, _UU("CMD_UTVPNCMD_CLIENT_NO_REMODE"));\r
+                       ReleaseCedar(cedar);\r
+                       return ERR_INTERNAL_ERROR;\r
+               }\r
+               else if (bad_pass)\r
+               {\r
+                       char *tmp;\r
+                       // パスワード違い\r
+                       c->Write(c, _UU("CMD_UTVPNCMD_PASSWORD_1"));\r
+                       tmp = c->ReadPassword(c, _UU("CMD_UTVPNCMD_PASSWORD_2"));\r
+                       c->Write(c, L"");\r
+\r
+                       if (tmp == NULL)\r
+                       {\r
+                               // キャンセル\r
+                               ReleaseCedar(cedar);\r
+                               return ERR_ACCESS_DENIED;\r
+                       }\r
+                       else\r
+                       {\r
+                               StrCpy(pass, sizeof(pass), tmp);\r
+                               Free(tmp);\r
+                       }\r
+\r
+                       goto RETRY;\r
+               }\r
+               else\r
+               {\r
+                       // 接続失敗\r
+                       CmdPrintError(c, ERR_CONNECT_FAILED);\r
+                       ReleaseCedar(cedar);\r
+                       return ERR_CONNECT_FAILED;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               // 接続完了\r
+               PC *pc = NewPc(c, client, target, cmdline);\r
+               PcMain(pc);\r
+               ret = pc->LastError;\r
+               FreePc(pc);\r
+       }\r
+\r
+       CcDisconnectRpc(client);\r
+\r
+       ReleaseCedar(cedar);\r
+\r
+       return ret;\r
+}\r
+\r
+\r
+// サーバー管理ツールプロセッサメイン\r
+void PsMain(PS *ps)\r
+{\r
+       char prompt[MAX_SIZE];\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (ps == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // CSV モードでなければ、接続が完了したメッセージを表示する\r
+       if(ps->Console->ConsoleType != CONSOLE_CSV)\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), _UU("CMD_UTVPNCMD_SERVER_CONNECTED"),\r
+                       ps->ServerName, ps->ServerPort);\r
+               ps->Console->Write(ps->Console, tmp);\r
+               ps->Console->Write(ps->Console, L"");\r
+\r
+               if (ps->HubName == NULL)\r
+               {\r
+                       // サーバー管理モード\r
+                       ps->Console->Write(ps->Console, _UU("CMD_UTVPNCMD_SERVER_CONNECTED_1"));\r
+               }\r
+               else\r
+               {\r
+                       // 仮想 HUB 管理モード\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CMD_UTVPNCMD_SERVER_CONNECTED_2"),\r
+                               ps->HubName);\r
+                       ps->Console->Write(ps->Console, tmp);\r
+               }\r
+               ps->Console->Write(ps->Console, L"");\r
+       }\r
+\r
+       // Caps を取得\r
+       ps->CapsList = ScGetCapsEx(ps->Rpc);\r
+\r
+       if (ps->AdminHub != NULL)\r
+       {\r
+               RPC_HUB_STATUS t;\r
+               UINT ret;\r
+               wchar_t tmp[MAX_SIZE];\r
+\r
+               // ADMINHUB で指定された仮想 HUB を選択する\r
+               Zero(&t, sizeof(t));\r
+\r
+               StrCpy(t.HubName, sizeof(t.HubName), ps->AdminHub);\r
+\r
+               ret = ScGetHubStatus(ps->Rpc, &t);\r
+               if (ret == ERR_NO_ERROR)\r
+               {\r
+                       // 成功\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CMD_Hub_Selected"), t.HubName);\r
+\r
+                       if (ps->HubName != NULL)\r
+                       {\r
+                               Free(ps->HubName);\r
+                       }\r
+                       ps->HubName = CopyStr(t.HubName);\r
+\r
+                       if( ps->Console->ConsoleType != CONSOLE_CSV)\r
+                       {\r
+                               ps->Console->Write(ps->Console, tmp);\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       // 失敗\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CMD_Hub_Select_Failed"), ps->AdminHub);\r
+\r
+                       ps->Console->Write(ps->Console, tmp);\r
+                       CmdPrintError(ps->Console, ret);\r
+               }\r
+       }\r
+\r
+       while (true)\r
+       {\r
+               // コマンドの定義\r
+               CMD cmd[] =\r
+               {\r
+                       {"About", PsAbout},\r
+                       {"Check", PtCheck},\r
+                       {"Crash", PsCrash},\r
+                       {"Flush", PsFlush},\r
+                       {"Debug", PsDebug},\r
+                       {"ServerInfoGet", PsServerInfoGet},\r
+                       {"ServerStatusGet", PsServerStatusGet},\r
+                       {"ListenerCreate", PsListenerCreate},\r
+                       {"ListenerDelete", PsListenerDelete},\r
+                       {"ListenerList", PsListenerList},\r
+                       {"ListenerEnable", PsListenerEnable},\r
+                       {"ListenerDisable", PsListenerDisable},\r
+                       {"ServerPasswordSet", PsServerPasswordSet},\r
+                       {"ClusterSettingGet", PsClusterSettingGet},\r
+                       {"ClusterSettingStandalone", PsClusterSettingStandalone},\r
+                       {"ClusterSettingController", PsClusterSettingController},\r
+                       {"ClusterSettingMember", PsClusterSettingMember},\r
+                       {"ClusterMemberList", PsClusterMemberList},\r
+                       {"ClusterMemberInfoGet", PsClusterMemberInfoGet},\r
+                       {"ClusterMemberCertGet", PsClusterMemberCertGet},\r
+                       {"ClusterConnectionStatusGet", PsClusterConnectionStatusGet},\r
+                       {"ServerCertGet", PsServerCertGet},\r
+                       {"ServerKeyGet", PsServerKeyGet},\r
+                       {"ServerCertSet", PsServerCertSet},\r
+                       {"ServerCipherGet", PsServerCipherGet},\r
+                       {"ServerCipherSet", PsServerCipherSet},\r
+                       {"KeepEnable", PsKeepEnable},\r
+                       {"KeepDisable", PsKeepDisable},\r
+                       {"KeepSet", PsKeepSet},\r
+                       {"KeepGet", PsKeepGet},\r
+                       {"SyslogGet", PsSyslogGet},\r
+                       {"SyslogDisable", PsSyslogDisable},\r
+                       {"SyslogEnable", PsSyslogEnable},\r
+                       {"ConnectionList", PsConnectionList},\r
+                       {"ConnectionGet", PsConnectionGet},\r
+                       {"ConnectionDisconnect", PsConnectionDisconnect},\r
+                       {"BridgeDeviceList", PsBridgeDeviceList},\r
+                       {"BridgeList", PsBridgeList},\r
+                       {"BridgeCreate", PsBridgeCreate},\r
+                       {"BridgeDelete", PsBridgeDelete},\r
+                       {"Caps", PsCaps},\r
+                       {"Reboot", PsReboot},\r
+                       {"ConfigGet", PsConfigGet},\r
+                       {"ConfigSet", PsConfigSet},\r
+                       {"RouterList", PsRouterList},\r
+                       {"RouterAdd", PsRouterAdd},\r
+                       {"RouterDelete", PsRouterDelete},\r
+                       {"RouterStart", PsRouterStart},\r
+                       {"RouterStop", PsRouterStop},\r
+                       {"RouterIfList", PsRouterIfList},\r
+                       {"RouterIfAdd", PsRouterIfAdd},\r
+                       {"RouterIfDel", PsRouterIfDel},\r
+                       {"RouterTableList", PsRouterTableList},\r
+                       {"RouterTableAdd", PsRouterTableAdd},\r
+                       {"RouterTableDel", PsRouterTableDel},\r
+                       {"LogFileList", PsLogFileList},\r
+                       {"LogFileGet", PsLogFileGet},\r
+                       {"HubCreate", PsHubCreate},\r
+                       {"HubCreateDynamic", PsHubCreateDynamic},\r
+                       {"HubCreateStatic", PsHubCreateStatic},\r
+                       {"HubDelete", PsHubDelete},\r
+                       {"HubSetStatic", PsHubSetStatic},\r
+                       {"HubSetDynamic", PsHubSetDynamic},\r
+                       {"HubList", PsHubList},\r
+                       {"Hub", PsHub},\r
+                       {"Online", PsOnline},\r
+                       {"Offline", PsOffline},\r
+                       {"SetMaxSession", PsSetMaxSession},\r
+                       {"SetHubPassword", PsSetHubPassword},\r
+                       {"SetEnumAllow", PsSetEnumAllow},\r
+                       {"SetEnumDeny", PsSetEnumDeny},\r
+                       {"OptionsGet", PsOptionsGet},\r
+                       {"RadiusServerSet", PsRadiusServerSet},\r
+                       {"RadiusServerDelete", PsRadiusServerDelete},\r
+                       {"RadiusServerGet", PsRadiusServerGet},\r
+                       {"StatusGet", PsStatusGet},\r
+                       {"LogGet", PsLogGet},\r
+                       {"LogEnable", PsLogEnable},\r
+                       {"LogDisable", PsLogDisable},\r
+                       {"LogSwitchSet", PsLogSwitchSet},\r
+                       {"LogPacketSaveType", PsLogPacketSaveType},\r
+                       {"CAList", PsCAList},\r
+                       {"CAAdd", PsCAAdd},\r
+                       {"CADelete", PsCADelete},\r
+                       {"CAGet", PsCAGet},\r
+                       {"CascadeList", PsCascadeList},\r
+                       {"CascadeCreate", PsCascadeCreate},\r
+                       {"CascadeSet", PsCascadeSet},\r
+                       {"CascadeGet", PsCascadeGet},\r
+                       {"CascadeDelete", PsCascadeDelete},\r
+                       {"CascadeUsernameSet", PsCascadeUsernameSet},\r
+                       {"CascadeAnonymousSet", PsCascadeAnonymousSet},\r
+                       {"CascadePasswordSet", PsCascadePasswordSet},\r
+                       {"CascadeCertSet", PsCascadeCertSet},\r
+                       {"CascadeCertGet", PsCascadeCertGet},\r
+                       {"CascadeEncryptEnable", PsCascadeEncryptEnable},\r
+                       {"CascadeEncryptDisable", PsCascadeEncryptDisable},\r
+                       {"CascadeCompressEnable", PsCascadeCompressEnable},\r
+                       {"CascadeCompressDisable", PsCascadeCompressDisable},\r
+                       {"CascadeProxyNone", PsCascadeProxyNone},\r
+                       {"CascadeProxyHttp", PsCascadeProxyHttp},\r
+                       {"CascadeProxySocks", PsCascadeProxySocks},\r
+                       {"CascadeServerCertEnable", PsCascadeServerCertEnable},\r
+                       {"CascadeServerCertDisable", PsCascadeServerCertDisable},\r
+                       {"CascadeServerCertSet", PsCascadeServerCertSet},\r
+                       {"CascadeServerCertDelete", PsCascadeServerCertDelete},\r
+                       {"CascadeServerCertGet", PsCascadeServerCertGet},\r
+                       {"CascadeDetailSet", PsCascadeDetailSet},\r
+                       {"CascadePolicySet", PsCascadePolicySet},\r
+                       {"PolicyList", PsPolicyList},\r
+                       {"CascadeStatusGet", PsCascadeStatusGet},\r
+                       {"CascadeRename", PsCascadeRename},\r
+                       {"CascadeOnline", PsCascadeOnline},\r
+                       {"CascadeOffline", PsCascadeOffline},\r
+                       {"AccessAdd", PsAccessAdd},\r
+                       {"AccessAddEx", PsAccessAddEx},\r
+                       {"AccessAdd6", PsAccessAdd6},\r
+                       {"AccessAddEx6", PsAccessAddEx6},\r
+                       {"AccessList", PsAccessList},\r
+                       {"AccessDelete", PsAccessDelete},\r
+                       {"AccessEnable", PsAccessEnable},\r
+                       {"AccessDisable", PsAccessDisable},\r
+                       {"UserList", PsUserList},\r
+                       {"UserCreate", PsUserCreate},\r
+                       {"UserSet", PsUserSet},\r
+                       {"UserDelete", PsUserDelete},\r
+                       {"UserGet", PsUserGet},\r
+                       {"UserAnonymousSet", PsUserAnonymousSet},\r
+                       {"UserPasswordSet", PsUserPasswordSet},\r
+                       {"UserCertSet", PsUserCertSet},\r
+                       {"UserCertGet", PsUserCertGet},\r
+                       {"UserSignedSet", PsUserSignedSet},\r
+                       {"UserRadiusSet", PsUserRadiusSet},\r
+                       {"UserNTLMSet", PsUserNTLMSet},\r
+                       {"UserPolicyRemove", PsUserPolicyRemove},\r
+                       {"UserPolicySet", PsUserPolicySet},\r
+                       {"UserExpiresSet", PsUserExpiresSet},\r
+                       {"GroupList", PsGroupList},\r
+                       {"GroupCreate", PsGroupCreate},\r
+                       {"GroupSet", PsGroupSet},\r
+                       {"GroupDelete", PsGroupDelete},\r
+                       {"GroupGet", PsGroupGet},\r
+                       {"GroupJoin", PsGroupJoin},\r
+                       {"GroupUnjoin", PsGroupUnjoin},\r
+                       {"GroupPolicyRemove", PsGroupPolicyRemove},\r
+                       {"GroupPolicySet", PsGroupPolicySet},\r
+                       {"SessionList", PsSessionList},\r
+                       {"SessionGet", PsSessionGet},\r
+                       {"SessionDisconnect", PsSessionDisconnect},\r
+                       {"MacTable", PsMacTable},\r
+                       {"MacDelete", PsMacDelete},\r
+                       {"IpTable", PsIpTable},\r
+                       {"IpDelete", PsIpDelete},\r
+                       {"SecureNatEnable", PsSecureNatEnable},\r
+                       {"SecureNatDisable", PsSecureNatDisable},\r
+                       {"SecureNatStatusGet", PsSecureNatStatusGet},\r
+                       {"SecureNatHostGet", PsSecureNatHostGet},\r
+                       {"SecureNatHostSet", PsSecureNatHostSet},\r
+                       {"NatGet", PsNatGet},\r
+                       {"NatEnable", PsNatEnable},\r
+                       {"NatDisable", PsNatDisable},\r
+                       {"NatSet", PsNatSet},\r
+                       {"NatTable", PsNatTable},\r
+                       {"DhcpGet", PsDhcpGet},\r
+                       {"DhcpEnable", PsDhcpEnable},\r
+                       {"DhcpDisable", PsDhcpDisable},\r
+                       {"DhcpSet", PsDhcpSet},\r
+                       {"DhcpTable", PsDhcpTable},\r
+                       {"AdminOptionList", PsAdminOptionList},\r
+                       {"AdminOptionSet", PsAdminOptionSet},\r
+                       {"ExtOptionList", PsExtOptionList},\r
+                       {"ExtOptionSet", PsExtOptionSet},\r
+                       {"CrlList", PsCrlList},\r
+                       {"CrlAdd", PsCrlAdd},\r
+                       {"CrlDel", PsCrlDel},\r
+                       {"CrlGet", PsCrlGet},\r
+                       {"AcList", PsAcList},\r
+                       {"AcAdd", PsAcAdd},\r
+                       {"AcAdd6", PsAcAdd6},\r
+                       {"AcDel", PsAcDel},\r
+                       {"MakeCert", PtMakeCert},\r
+                       {"TrafficClient", PtTrafficClient},\r
+                       {"TrafficServer", PtTrafficServer},\r
+                       {"LicenseAdd", PsLicenseAdd},\r
+                       {"LicenseDel", PsLicenseDel},\r
+                       {"LicenseList", PsLicenseList},\r
+                       {"LicenseStatus", PsLicenseStatus},\r
+               };\r
+\r
+               // プロンプトの生成\r
+               if (ps->HubName == NULL)\r
+               {\r
+                       Format(prompt, sizeof(prompt), "VPN Server>");\r
+               }\r
+               else\r
+               {\r
+                       Format(prompt, sizeof(prompt), "VPN Server/%s>", ps->HubName);\r
+               }\r
+\r
+               if (DispatchNextCmdEx(ps->Console, ps->CmdLine, prompt, cmd, sizeof(cmd) / sizeof(cmd[0]), ps) == false)\r
+               {\r
+                       break;\r
+               }\r
+               ps->LastError = ps->Console->RetCode;\r
+\r
+               if (ps->LastError == ERR_NO_ERROR && ps->Console->ConsoleType != CONSOLE_CSV)\r
+               {\r
+                       ps->Console->Write(ps->Console, _UU("CMD_MSG_OK"));\r
+                       ps->Console->Write(ps->Console, L"");\r
+               }\r
+\r
+               if (ps->CmdLine != NULL)\r
+               {\r
+                       break;\r
+               }\r
+       }\r
+\r
+       // Caps を解放\r
+       FreeCapsList(ps->CapsList);\r
+       ps->CapsList = NULL;\r
+}\r
+\r
+// 新しいコマンド関数のテンプレート\r
+UINT PsXxx(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret;\r
+       RPC_LISTENER t;\r
+       PARAM args[] =\r
+       {\r
+               {"[port]", CmdPromptPort, _UU("CMD_ListenerCreate_PortPrompt"), CmdEvalPort, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.Enable = true;\r
+       t.Port = ToInt(GetParamStr(o, "[port]"));\r
+\r
+       ret = ScCreateListener(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// スタンドアロンモードに設定\r
+UINT PsClusterSettingStandalone(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_FARM t;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.ServerType = SERVER_TYPE_STANDALONE;\r
+\r
+       // RPC 呼び出し\r
+       ret = ScSetFarmSetting(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// クラスタコントローラモードに設定\r
+UINT PsClusterSettingController(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_FARM t;\r
+       UINT weight;\r
+       PARAM args[] =\r
+       {\r
+               {"WEIGHT", NULL, NULL, NULL, NULL},\r
+               {"ONLY", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       weight = GetParamInt(o, "WEIGHT");\r
+       if (weight == 0)\r
+       {\r
+               weight = FARM_DEFAULT_WEIGHT;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.ServerType = SERVER_TYPE_FARM_CONTROLLER;\r
+       t.Weight = weight;\r
+       t.ControllerOnly = GetParamYes(o, "ONLY");\r
+\r
+       // RPC 呼び出し\r
+       ret = ScSetFarmSetting(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// IP アドレスの評価\r
+bool CmdEvalIp(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (UniIsEmptyStr(str))\r
+       {\r
+               return true;\r
+       }\r
+\r
+       if (UniStrToIP32(str) == 0 && UniStrCmpi(str, L"0.0.0.0") != 0)\r
+       {\r
+               wchar_t *msg = (param == NULL) ? _UU("CMD_IP_EVAL_FAILED") : (wchar_t *)param;\r
+               c->Write(c, msg);\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// 文字列をポートリストに変換\r
+LIST *StrToPortList(char *str)\r
+{\r
+       LIST *o;\r
+       TOKEN_LIST *t;\r
+       UINT i;\r
+       if (str == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       // トークンに変換\r
+       t = ParseToken(str, ", ");\r
+       if (t == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+       if (t->NumTokens == 0)\r
+       {\r
+               FreeToken(t);\r
+               return NULL;\r
+       }\r
+\r
+       o = NewListFast(NULL);\r
+\r
+       for (i = 0;i < t->NumTokens;i++)\r
+       {\r
+               char *s = t->Token[i];\r
+               UINT n;\r
+               if (IsNum(s) == false)\r
+               {\r
+                       ReleaseList(o);\r
+                       FreeToken(t);\r
+                       return NULL;\r
+               }\r
+               n = ToInt(s);\r
+               if (n == 0 || n >= 65536)\r
+               {\r
+                       ReleaseList(o);\r
+                       FreeToken(t);\r
+                       return NULL;\r
+               }\r
+               if (IsInList(o, (void *)n))\r
+               {\r
+                       ReleaseList(o);\r
+                       FreeToken(t);\r
+                       return NULL;\r
+               }\r
+               Add(o, (void *)n);\r
+       }\r
+\r
+       FreeToken(t);\r
+\r
+       if (LIST_NUM(o) > MAX_PUBLIC_PORT_NUM)\r
+       {\r
+               ReleaseList(o);\r
+               return NULL;\r
+       }\r
+\r
+       return o;\r
+}\r
+\r
+// クラスタメンバモードに設定\r
+UINT PsClusterSettingMember(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_FARM t;\r
+       char *host_and_port;\r
+       char *host;\r
+       UINT port;\r
+       UINT weight;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[server:port]", CmdPrompt, _UU("CMD_ClusterSettingMember_Prompt_HOST_1"), CmdEvalHostAndPort, NULL},\r
+               {"IP", PsClusterSettingMemberPromptIp, NULL, CmdEvalIp, NULL},\r
+               {"PORTS", PsClusterSettingMemberPromptPorts, NULL, CmdEvalPortList, NULL},\r
+               {"PASSWORD", CmdPromptChoosePassword, NULL, NULL, NULL},\r
+               {"WEIGHT", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       weight = GetParamInt(o, "WEIGHT");\r
+\r
+       if (weight == 0)\r
+       {\r
+               weight = FARM_DEFAULT_WEIGHT;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       host_and_port = GetParamStr(o, "[server:port]");\r
+       if (ParseHostPort(host_and_port, &host, &port, 0))\r
+       {\r
+               char *pw;\r
+               char *ports_str;\r
+               LIST *ports;\r
+               UINT i;\r
+\r
+               StrCpy(t.ControllerName, sizeof(t.ControllerName), host);\r
+               t.ControllerPort = port;\r
+               Free(host);\r
+\r
+               pw = GetParamStr(o, "PASSWORD");\r
+\r
+               Hash(t.MemberPassword, pw, StrLen(pw), true);\r
+               t.PublicIp = StrToIP32(GetParamStr(o, "IP"));\r
+               t.ServerType = SERVER_TYPE_FARM_MEMBER;\r
+\r
+               ports_str = GetParamStr(o, "PORTS");\r
+\r
+               ports = StrToPortList(ports_str);\r
+\r
+               t.NumPort = LIST_NUM(ports);\r
+               t.Ports = ZeroMalloc(sizeof(UINT) * t.NumPort);\r
+\r
+               for (i = 0;i < t.NumPort;i++)\r
+               {\r
+                       t.Ports[i] = (UINT)LIST_DATA(ports, i);\r
+               }\r
+\r
+               t.Weight = weight;\r
+\r
+               ReleaseList(ports);\r
+\r
+               // RPC 呼び出し\r
+               ret = ScSetFarmSetting(ps->Rpc, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcFarm(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ポート一覧の評価\r
+bool CmdEvalPortList(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       char *s;\r
+       bool ret = false;\r
+       LIST *o;\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       s = CopyUniToStr(str);\r
+\r
+       o = StrToPortList(s);\r
+\r
+       if (o != NULL)\r
+       {\r
+               ret = true;\r
+       }\r
+\r
+       ReleaseList(o);\r
+\r
+       Free(s);\r
+\r
+       if (ret == false)\r
+       {\r
+               c->Write(c, _UU("CMD_PORTLIST_EVAL_FAILED"));\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// ホスト名とポート番号の形式の文字列のチェック\r
+bool CmdEvalHostAndPort(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       char *tmp;\r
+       bool ret = false;\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       tmp = CopyUniToStr(str);\r
+\r
+       ret = ParseHostPort(tmp, NULL, NULL, (UINT)param);\r
+\r
+       if (ret == false)\r
+       {\r
+               c->Write(c, param == NULL ? _UU("CMD_HOSTPORT_EVAL_FAILED") : (wchar_t *)param);\r
+       }\r
+\r
+       Free(tmp);\r
+\r
+       return ret;\r
+}\r
+\r
+// 公開 ポート番号の入力\r
+wchar_t *PsClusterSettingMemberPromptPorts(CONSOLE *c, void *param)\r
+{\r
+       wchar_t *ret;\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       c->Write(c, _UU("CMD_ClusterSettingMember_Prompt_PORT_1"));\r
+       c->Write(c, L"");\r
+\r
+       ret = c->ReadLine(c, _UU("CMD_ClusterSettingMember_Prompt_PORT_2"), true);\r
+\r
+       return ret;\r
+}\r
+\r
+// 公開 IP アドレスの入力\r
+wchar_t *PsClusterSettingMemberPromptIp(CONSOLE *c, void *param)\r
+{\r
+       wchar_t *ret;\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       c->Write(c, _UU("CMD_ClusterSettingMember_Prompt_IP_1"));\r
+       c->Write(c, L"");\r
+\r
+       ret = c->ReadLine(c, _UU("CMD_ClusterSettingMember_Prompt_IP_2"), true);\r
+\r
+       return ret;\r
+}\r
+\r
+// クラスタメンバリストの表示\r
+UINT PsClusterMemberList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_FARM t;\r
+       CT *ct;\r
+       UINT i;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumFarmMember(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       ct = CtNew();\r
+\r
+       CtInsertColumn(ct, _UU("CMD_ID"), true);\r
+       CtInsertColumn(ct, _UU("SM_FM_COLUMN_1"), false);\r
+       CtInsertColumn(ct, _UU("SM_FM_COLUMN_2"), false);\r
+       CtInsertColumn(ct, _UU("SM_FM_COLUMN_3"), false);\r
+       CtInsertColumn(ct, _UU("SM_FM_COLUMN_4"), true);\r
+       CtInsertColumn(ct, _UU("SM_FM_COLUMN_5"), true);\r
+       CtInsertColumn(ct, _UU("SM_FM_COLUMN_6"), true);\r
+       CtInsertColumn(ct, _UU("SM_FM_COLUMN_7"), true);\r
+       CtInsertColumn(ct, _UU("SM_FM_COLUMN_8"), true);\r
+       CtInsertColumn(ct, _UU("SM_FM_COLUMN_9"), true);\r
+\r
+       for (i = 0;i < t.NumFarm;i++)\r
+       {\r
+               RPC_ENUM_FARM_ITEM *e = &t.Farms[i];\r
+               wchar_t tmp0[64];\r
+               wchar_t tmp1[MAX_SIZE];\r
+               wchar_t tmp2[MAX_SIZE];\r
+               wchar_t tmp3[64];\r
+               wchar_t tmp4[64];\r
+               wchar_t tmp5[64];\r
+               wchar_t tmp6[64];\r
+               wchar_t tmp7[64];\r
+               wchar_t tmp8[64];\r
+\r
+               GetDateTimeStrEx64(tmp1, sizeof(tmp1), SystemToLocal64(e->ConnectedTime), NULL);\r
+               StrToUni(tmp2, sizeof(tmp2), e->Hostname);\r
+               UniToStru(tmp3, e->Point);\r
+               UniToStru(tmp4, e->NumSessions);\r
+               UniToStru(tmp5, e->NumTcpConnections);\r
+               UniToStru(tmp6, e->NumHubs);\r
+               UniToStru(tmp7, e->AssignedClientLicense);\r
+               UniToStru(tmp8, e->AssignedBridgeLicense);\r
+\r
+               UniToStru(tmp0, e->Id);\r
+\r
+               CtInsert(ct, tmp0,\r
+                       e->Controller ? _UU("SM_FM_CONTROLLER") : _UU("SM_FM_MEMBER"),\r
+                       tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8);\r
+       }\r
+\r
+       CtFree(ct, c);\r
+\r
+       FreeRpcEnumFarm(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// クラスタ メンバの情報の取得\r
+UINT PsClusterMemberInfoGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_FARM_INFO t;\r
+       CT *ct;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[id]", CmdPrompt, _UU("CMD_ClusterMemberInfoGet_PROMPT_ID"), NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.Id = UniToInt(GetParamUniStr(o, "[id]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetFarmInfo(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       ct = CtNewStandard();\r
+\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               char str[MAX_SIZE];\r
+               UINT i;\r
+\r
+               CtInsert(ct, _UU("SM_FMINFO_TYPE"),\r
+                       t.Controller ? _UU("SM_FARM_CONTROLLER") : _UU("SM_FARM_MEMBER"));\r
+\r
+               GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.ConnectedTime), NULL);\r
+               CtInsert(ct, _UU("SM_FMINFO_CONNECT_TIME"), tmp);\r
+\r
+               IPToStr32(str, sizeof(str), t.Ip);\r
+               StrToUni(tmp, sizeof(tmp), str);\r
+               CtInsert(ct, _UU("SM_FMINFO_IP"), tmp);\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.Hostname);\r
+               CtInsert(ct, _UU("SM_FMINFO_HOSTNAME"), tmp);\r
+\r
+               UniToStru(tmp, t.Point);\r
+               CtInsert(ct, _UU("SM_FMINFO_POINT"), tmp);\r
+\r
+               UniToStru(tmp, t.Weight);\r
+               CtInsert(ct, _UU("SM_FMINFO_WEIGHT"), tmp);\r
+\r
+               UniToStru(tmp, t.NumPort);\r
+               CtInsert(ct, _UU("SM_FMINFO_NUM_PORT"), tmp);\r
+\r
+               for (i = 0;i < t.NumPort;i++)\r
+               {\r
+                       wchar_t tmp2[MAX_SIZE];\r
+                       UniFormat(tmp, sizeof(tmp), _UU("SM_FMINFO_PORT"), i + 1);\r
+                       UniToStru(tmp2, t.Ports[i]);\r
+                       CtInsert(ct, tmp, tmp2);\r
+               }\r
+\r
+               UniToStru(tmp, t.NumFarmHub);\r
+               CtInsert(ct, _UU("SM_FMINFO_NUM_HUB"), tmp);\r
+\r
+               for (i = 0;i < t.NumFarmHub;i++)\r
+               {\r
+                       wchar_t tmp2[MAX_SIZE];\r
+                       UniFormat(tmp, sizeof(tmp), _UU("SM_FMINFO_HUB"), i + 1);\r
+                       UniFormat(tmp2, sizeof(tmp2),\r
+                               t.FarmHubs[i].DynamicHub ? _UU("SM_FMINFO_HUB_TAG_2") : _UU("SM_FMINFO_HUB_TAG_1"),\r
+                               t.FarmHubs[i].HubName);\r
+                       CtInsert(ct, tmp, tmp2);\r
+               }\r
+\r
+               UniToStru(tmp, t.NumSessions);\r
+               CtInsert(ct, _UU("SM_FMINFO_NUM_SESSION"), tmp);\r
+\r
+               UniToStru(tmp, t.NumTcpConnections);\r
+               CtInsert(ct, _UU("SM_FMINFO_NUN_CONNECTION"), tmp);\r
+       }\r
+\r
+       CtFree(ct, c);\r
+\r
+       FreeRpcFarmInfo(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// クラスタ メンバの証明書の取得\r
+UINT PsClusterMemberCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_FARM_INFO t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[id]", CmdPrompt, _UU("CMD_ClusterMemberCertGet_PROMPT_ID"), NULL, NULL},\r
+               {"SAVECERT", CmdPrompt, _UU("CMD_SAVECERTPATH"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       t.Id = UniToInt(GetParamUniStr(o, "[id]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetFarmInfo(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               X *x = t.ServerCert;\r
+               char *filename = GetParamStr(o, "SAVECERT");\r
+\r
+               if (XToFile(x, filename, true) == false)\r
+               {\r
+                       c->Write(c, _UU("CMD_SAVECERT_FAILED"));\r
+\r
+                       ret = ERR_INTERNAL_ERROR;\r
+               }\r
+       }\r
+\r
+       FreeRpcFarmInfo(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// クラスタ コントローラへの接続状態の取得\r
+UINT PsClusterConnectionStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_FARM_CONNECTION_STATUS t;\r
+       wchar_t tmp[MAX_SIZE];\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetFarmConnectionStatus(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct = CtNewStandard();\r
+               char str[MAX_SIZE];\r
+\r
+               if (t.Online == false)\r
+               {\r
+                       CtInsert(ct, _UU("SM_FC_IP"), _UU("SM_FC_NOT_CONNECTED"));\r
+\r
+                       CtInsert(ct, _UU("SM_FC_PORT"), _UU("SM_FC_NOT_CONNECTED"));\r
+               }\r
+               else\r
+               {\r
+                       IPToStr32(str, sizeof(str), t.Ip);\r
+                       StrToUni(tmp, sizeof(tmp), str);\r
+                       CtInsert(ct, _UU("SM_FC_IP"), tmp);\r
+\r
+                       UniToStru(tmp, t.Port);\r
+                       CtInsert(ct, _UU("SM_FC_PORT"), tmp);\r
+               }\r
+\r
+               CtInsert(ct,\r
+                       _UU("SM_FC_STATUS"),\r
+                       t.Online ? _UU("SM_FC_ONLINE") : _UU("SM_FC_OFFLINE"));\r
+\r
+               if (t.Online == false)\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("SM_FC_ERROR_TAG"), _E(t.LastError), t.LastError);\r
+                       CtInsert(ct,\r
+                               _UU("SM_FC_LAST_ERROR"), tmp);\r
+               }\r
+\r
+               GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.StartedTime), NULL);\r
+               CtInsert(ct, _UU("SM_FC_START_TIME"), tmp);\r
+\r
+               GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.FirstConnectedTime), NULL);\r
+               CtInsert(ct, _UU("SM_FC_FIRST_TIME"), tmp);\r
+\r
+               //if (t.Online == false)\r
+               {\r
+                       GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.CurrentConnectedTime), NULL);\r
+                       CtInsert(ct, _UU("SM_FC_CURRENT_TIME"), tmp);\r
+               }\r
+\r
+               UniToStru(tmp, t.NumTry);\r
+               CtInsert(ct, _UU("SM_FC_NUM_TRY"), tmp);\r
+\r
+               UniToStru(tmp, t.NumConnected);\r
+               CtInsert(ct, _UU("SM_FC_NUM_CONNECTED"), tmp);\r
+\r
+               UniToStru(tmp, t.NumFailed);\r
+               CtInsert(ct, _UU("SM_FC_NUM_FAILED"), tmp);\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// VPN Server の SSL 証明書の取得\r
+UINT PsServerCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_KEY_PAIR t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[cert]", CmdPrompt, _UU("CMD_SAVECERTPATH"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetServerCert(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       if (XToFile(t.Cert, GetParamStr(o, "[cert]"), true) == false)\r
+       {\r
+               c->Write(c, _UU("CMD_SAVECERT_FAILED"));\r
+       }\r
+\r
+       FreeRpcKeyPair(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// VPN Server の SSL 証明書の秘密鍵の取得\r
+UINT PsServerKeyGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_KEY_PAIR t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[key]", CmdPrompt, _UU("CMD_SAVEKEYPATH"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetServerCert(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       if (t.Key != NULL)\r
+       {\r
+               if (KToFile(t.Key, GetParamStr(o, "[key]"), true, NULL) == false)\r
+               {\r
+                       c->Write(c, _UU("CMD_SAVEKEY_FAILED"));\r
+               }\r
+       }\r
+       else\r
+       {\r
+               ret = ERR_NOT_ENOUGH_RIGHT;\r
+               CmdPrintError(c, ret);\r
+       }\r
+\r
+       FreeRpcKeyPair(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 証明書と秘密鍵の読み込み\r
+bool CmdLoadCertAndKey(CONSOLE *c, X **xx, K **kk, char *cert_filename, char *key_filename)\r
+{\r
+       X *x;\r
+       K *k;\r
+       // 引数チェック\r
+       if (c == NULL || cert_filename == NULL || key_filename == NULL || xx == NULL || kk == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       x = FileToX(cert_filename);\r
+       if (x == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_LOADCERT_FAILED"));\r
+               return false;\r
+       }\r
+\r
+       k = CmdLoadKey(c, key_filename);\r
+       if (k == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_LOADKEY_FAILED"));\r
+               FreeX(x);\r
+               return false;\r
+       }\r
+\r
+       if (CheckXandK(x, k) == false)\r
+       {\r
+               c->Write(c, _UU("CMD_KEYPAIR_FAILED"));\r
+               FreeX(x);\r
+               FreeK(k);\r
+\r
+               return false;\r
+       }\r
+\r
+       *xx = x;\r
+       *kk = k;\r
+\r
+       return true;\r
+}\r
+\r
+// 秘密鍵の読み込み\r
+K *CmdLoadKey(CONSOLE *c, char *filename)\r
+{\r
+       BUF *b;\r
+       // 引数チェック\r
+       if (c == NULL || filename == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       b = ReadDump(filename);\r
+       if (b == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_LOADCERT_FAILED"));\r
+               return NULL;\r
+       }\r
+       else\r
+       {\r
+               K *key;\r
+               if (IsEncryptedK(b, true) == false)\r
+               {\r
+                       key = BufToK(b, true, IsBase64(b), NULL);\r
+               }\r
+               else\r
+               {\r
+                       c->Write(c, _UU("CMD_LOADKEY_ENCRYPTED_1"));\r
+\r
+                       while (true)\r
+                       {\r
+                               char *pass = c->ReadPassword(c, _UU("CMD_LOADKEY_ENCRYPTED_2"));\r
+\r
+                               if (pass == NULL)\r
+                               {\r
+                                       FreeBuf(b);\r
+                                       return NULL;\r
+                               }\r
+\r
+                               key = BufToK(b, true, IsBase64(b), pass);\r
+                               Free(pass);\r
+\r
+                               if (key != NULL)\r
+                               {\r
+                                       break;\r
+                               }\r
+\r
+                               c->Write(c, _UU("CMD_LOADKEY_ENCRYPTED_3"));\r
+                       }\r
+               }\r
+\r
+               FreeBuf(b);\r
+\r
+               return key;\r
+       }\r
+}\r
+\r
+// VPN Server の SSL 証明書と秘密鍵の設定\r
+UINT PsServerCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_KEY_PAIR t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"LOADCERT", CmdPrompt, _UU("CMD_LOADCERTPATH"), CmdEvalIsFile, NULL},\r
+               {"LOADKEY", CmdPrompt, _UU("CMD_LOADKEYPATH"), CmdEvalIsFile, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       if (CmdLoadCertAndKey(c, &t.Cert, &t.Key,\r
+               GetParamStr(o, "LOADCERT"),\r
+               GetParamStr(o, "LOADKEY")))\r
+       {\r
+               // RPC 呼び出し\r
+               ret = ScSetServerCert(ps->Rpc, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcKeyPair(&t);\r
+       }\r
+       else\r
+       {\r
+               ret = ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// VPN 通信で使用される暗号化アルゴリズムの取得\r
+UINT PsServerCipherGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_STR t;\r
+       TOKEN_LIST *ciphers;\r
+       UINT i;\r
+       wchar_t tmp[MAX_SIZE];\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetServerCipher(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       ciphers = GetCipherList();\r
+\r
+       c->Write(c, _UU("CMD_ServerCipherGet_SERVER"));\r
+\r
+       UniFormat(tmp, sizeof(tmp), L" %S", t.String);\r
+       c->Write(c, tmp);\r
+\r
+       c->Write(c, L"");\r
+       c->Write(c, _UU("CMD_ServerCipherGet_CIPHERS"));\r
+\r
+       for (i = 0;i < ciphers->NumTokens;i++)\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), L" %S", ciphers->Token[i]);\r
+               c->Write(c, tmp);\r
+       }\r
+\r
+       FreeRpcStr(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// VPN 通信で使用される暗号化アルゴリズムの設定\r
+UINT PsServerCipherSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_STR t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_ServerCipherSet_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.String = CopyStr(GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScSetServerCipher(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcStr(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// インターネット接続の維持機能の有効化\r
+UINT PsKeepEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_KEEP t;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetKeep(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       t.UseKeepConnect = true;\r
+\r
+       ret = ScSetKeep(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// インターネット接続の維持機能の無効化\r
+UINT PsKeepDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_KEEP t;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetKeep(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       t.UseKeepConnect = false;\r
+\r
+       ret = ScSetKeep(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// tcp または udp の評価\r
+bool CmdEvalTcpOrUdp(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (UniStrCmpi(str, L"tcp") == 0 || UniStrCmpi(str, L"udp") == 0)\r
+       {\r
+               return true;\r
+       }\r
+\r
+       c->Write(c, _UU("CMD_KeepSet_EVAL_TCP_UDP"));\r
+\r
+       return false;\r
+}\r
+\r
+// syslog 設定の有効化\r
+UINT PsSyslogEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       SYSLOG_SETTING t;\r
+       CMD_EVAL_MIN_MAX minmax = {"CMD_SyslogEnable_MINMAX", 1, 3};\r
+       char *host;\r
+       UINT port;\r
+\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[1|2|3]", CmdPrompt, _UU("CMD_SyslogEnable_Prompt_123"), CmdEvalMinMax, &minmax},\r
+               {"HOST", CmdPrompt, _UU("CMD_SyslogEnable_Prompt_HOST"), CmdEvalHostAndPort, (void *)SYSLOG_PORT},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       if (ParseHostPort(GetParamStr(o, "HOST"), &host, &port, SYSLOG_PORT))\r
+       {\r
+               StrCpy(t.Hostname, sizeof(t.Hostname), host);\r
+               t.Port = port;\r
+               t.SaveType = GetParamInt(o, "[1|2|3]");\r
+\r
+               Free(host);\r
+\r
+               // RPC 呼び出し\r
+               ret = ScSetSysLog(ps->Rpc, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// syslog 設定の無効化\r
+UINT PsSyslogDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       SYSLOG_SETTING t;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetSysLog(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       t.SaveType = SYSLOG_NONE;\r
+\r
+       // RPC 呼び出し\r
+       ret = ScSetSysLog(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// syslog 設定の取得\r
+UINT PsSyslogGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       SYSLOG_SETTING t;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetSysLog(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               CT *ct = CtNewStandard();\r
+\r
+               CtInsert(ct, _UU("CMD_SyslogGet_COLUMN_1"), GetSyslogSettingName(t.SaveType));\r
+\r
+               if (t.SaveType != SYSLOG_NONE)\r
+               {\r
+                       StrToUni(tmp, sizeof(tmp), t.Hostname);\r
+                       CtInsert(ct, _UU("CMD_SyslogGet_COLUMN_2"), tmp);\r
+\r
+                       UniToStru(tmp, t.Port);\r
+                       CtInsert(ct, _UU("CMD_SyslogGet_COLUMN_3"), tmp);\r
+               }\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// syslog 設定名を取得\r
+wchar_t *GetSyslogSettingName(UINT n)\r
+{\r
+       char tmp[MAX_PATH];\r
+\r
+       Format(tmp, sizeof(tmp), "SM_SYSLOG_%u", n);\r
+\r
+       return _UU(tmp);\r
+}\r
+\r
+// インターネット接続の維持機能の設定\r
+UINT PsKeepSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_KEEP t;\r
+       char *host;\r
+       UINT port;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"HOST", CmdPrompt, _UU("CMD_KeepSet_PROMPT_HOST"), CmdEvalHostAndPort, NULL},\r
+               {"PROTOCOL", CmdPrompt, _UU("CMD_KeepSet_PROMPT_PROTOCOL"), CmdEvalTcpOrUdp, NULL},\r
+               {"INTERVAL", CmdPrompt, _UU("CMD_KeepSet_PROMPT_INTERVAL"), NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetKeep(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       if (ParseHostPort(GetParamStr(o, "HOST"), &host, &port, 0))\r
+       {\r
+               StrCpy(t.KeepConnectHost, sizeof(t.KeepConnectHost), host);\r
+               t.KeepConnectPort = port;\r
+               t.KeepConnectInterval = GetParamInt(o, "INTERVAL");\r
+               t.KeepConnectProtocol = (StrCmpi(GetParamStr(o, "PROTOCOL"), "tcp") == 0) ? 0 : 1;\r
+               Free(host);\r
+\r
+               // RPC 呼び出し\r
+               ret = ScSetKeep(ps->Rpc, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// インターネット接続の維持機能の取得\r
+UINT PsKeepGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_KEEP t;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetKeep(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               CT *ct = CtNewStandard();\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.KeepConnectHost);\r
+               CtInsert(ct, _UU("CMD_KeepGet_COLUMN_1"), tmp);\r
+\r
+               UniToStru(tmp, t.KeepConnectPort);\r
+               CtInsert(ct, _UU("CMD_KeepGet_COLUMN_2"), tmp);\r
+\r
+               UniToStru(tmp, t.KeepConnectInterval);\r
+               CtInsert(ct, _UU("CMD_KeepGet_COLUMN_3"), tmp);\r
+\r
+               CtInsert(ct, _UU("CMD_KeepGet_COLUMN_4"),\r
+                       t.KeepConnectProtocol == 0 ? L"TCP/IP" : L"UDP/IP");\r
+\r
+               CtInsert(ct, _UU("CMD_KeepGet_COLUMN_5"),\r
+                       t.UseKeepConnect ? _UU("SM_ACCESS_ENABLE") : _UU("SM_ACCESS_DISABLE"));\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// コネクション種類文字列の取得\r
+wchar_t *GetConnectionTypeStr(UINT type)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       Format(tmp, sizeof(tmp), "SM_CONNECTION_TYPE_%u", type);\r
+\r
+       return _UU(tmp);\r
+}\r
+\r
+// VPN Server に接続中の TCP コネクション一覧の取得\r
+UINT PsConnectionList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_CONNECTION t;\r
+       UINT i;\r
+       CT *ct;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumConnection(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       ct = CtNew();\r
+       CtInsertColumn(ct, _UU("SM_CONN_COLUMN_1"), false);\r
+       CtInsertColumn(ct, _UU("SM_CONN_COLUMN_2"), false);\r
+       CtInsertColumn(ct, _UU("SM_CONN_COLUMN_3"), false);\r
+       CtInsertColumn(ct, _UU("SM_CONN_COLUMN_4"), false);\r
+\r
+       for (i = 0;i < t.NumConnection;i++)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               wchar_t name[MAX_SIZE];\r
+               wchar_t datetime[MAX_SIZE];\r
+               RPC_ENUM_CONNECTION_ITEM *e = &t.Connections[i];\r
+\r
+               StrToUni(name, sizeof(name), e->Name);\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_HOSTNAME_AND_PORT"), e->Hostname, e->Port);\r
+               GetDateTimeStrEx64(datetime, sizeof(datetime), SystemToLocal64(e->ConnectedTime), NULL);\r
+\r
+               CtInsert(ct, name, tmp, datetime,\r
+                       GetConnectionTypeStr(e->Type));\r
+       }\r
+\r
+       CtFree(ct, c);\r
+\r
+       FreeRpcEnumConnetion(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// VPN Server に接続中の TCP コネクションの情報の取得\r
+UINT PsConnectionGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CONNECTION_INFO t;\r
+       CT *ct;\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_ConnectionGet_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetConnectionInfo(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               ct = CtNewStandard();\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.Name);\r
+               CtInsert(ct, _UU("SM_CONNINFO_NAME"), tmp);\r
+\r
+               CtInsert(ct, _UU("SM_CONNINFO_TYPE"), GetConnectionTypeStr(t.Type));\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.Hostname);\r
+               CtInsert(ct, _UU("SM_CONNINFO_HOSTNAME"), tmp);\r
+\r
+               UniToStru(tmp, t.Port);\r
+               CtInsert(ct, _UU("SM_CONNINFO_PORT"), tmp);\r
+\r
+               GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.ConnectedTime), NULL);\r
+               CtInsert(ct, _UU("SM_CONNINFO_TIME"), tmp);\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.ServerStr);\r
+               CtInsert(ct, _UU("SM_CONNINFO_SERVER_STR"), tmp);\r
+\r
+               UniFormat(tmp, sizeof(tmp), L"%u.%02u", t.ServerVer / 100, t.ServerVer % 100);\r
+               CtInsert(ct, _UU("SM_CONNINFO_SERVER_VER"), tmp);\r
+\r
+               UniToStru(tmp, t.ServerBuild);\r
+               CtInsert(ct, _UU("SM_CONNINFO_SERVER_BUILD"), tmp);\r
+\r
+               if (StrLen(t.ClientStr) != 0)\r
+               {\r
+                       StrToUni(tmp, sizeof(tmp), t.ClientStr);\r
+                       CtInsert(ct, _UU("SM_CONNINFO_CLIENT_STR"), tmp);\r
+\r
+                       UniFormat(tmp, sizeof(tmp), L"%u.%02u", t.ClientVer / 100, t.ClientVer % 100);\r
+                       CtInsert(ct, _UU("SM_CONNINFO_CLIENT_VER"), tmp);\r
+\r
+                       UniToStru(tmp, t.ClientBuild);\r
+                       CtInsert(ct, _UU("SM_CONNINFO_CLIENT_BUILD"), tmp);\r
+               }\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// VPN Server に接続中の TCP コネクションの切断\r
+UINT PsConnectionDisconnect(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_DISCONNECT_CONNECTION t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_ConnectionDisconnect_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDisconnectConnection(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ローカル ブリッジに使用できる LAN カード一覧の取得\r
+UINT PsBridgeDeviceList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_ETH t;\r
+       UINT i;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumEthernet(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       for (i = 0;i < t.NumItem;i++)\r
+       {\r
+               RPC_ENUM_ETH_ITEM *item = &t.Items[i];\r
+               wchar_t tmp[MAX_SIZE * 2];\r
+\r
+               if(UniIsEmptyStr(item->NetworkConnectionName) == false)\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), BRIDGE_NETWORK_CONNECTION_STR, item->NetworkConnectionName, item->DeviceName);\r
+               }\r
+               else\r
+               {\r
+                       StrToUni(tmp, sizeof(tmp), item->DeviceName);\r
+               }\r
+               c->Write(c, tmp);\r
+       }\r
+\r
+       FreeRpcEnumEth(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ローカル ブリッジ接続の一覧の取得\r
+UINT PsBridgeList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_LOCALBRIDGE t;\r
+       UINT i;\r
+       CT *ct;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumLocalBridge(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       ct = CtNew();\r
+\r
+       CtInsertColumn(ct, _UU("SM_BRIDGE_COLUMN_1"), false);\r
+       CtInsertColumn(ct, _UU("SM_BRIDGE_COLUMN_2"), false);\r
+       CtInsertColumn(ct, _UU("SM_BRIDGE_COLUMN_3"), false);\r
+       CtInsertColumn(ct, _UU("SM_BRIDGE_COLUMN_4"), false);\r
+\r
+       for (i = 0;i < t.NumItem;i++)\r
+       {\r
+               RPC_LOCALBRIDGE *e = &t.Items[i];\r
+               wchar_t name[MAX_SIZE];\r
+               wchar_t nic[MAX_SIZE];\r
+               wchar_t hub[MAX_SIZE];\r
+               wchar_t *status = _UU("SM_BRIDGE_OFFLINE");\r
+\r
+               UniToStru(name, i + 1);\r
+               StrToUni(nic, sizeof(nic), e->DeviceName);\r
+               StrToUni(hub, sizeof(hub), e->HubName);\r
+\r
+               if (e->Online)\r
+               {\r
+                       status = e->Active ? _UU("SM_BRIDGE_ONLINE") : _UU("SM_BRIDGE_ERROR");\r
+               }\r
+\r
+               CtInsert(ct, name, hub, nic, status);\r
+       }\r
+\r
+       CtFree(ct, c);\r
+\r
+       FreeRpcEnumLocalBridge(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ローカル ブリッジ接続の作成\r
+UINT PsBridgeCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_LOCALBRIDGE t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[hubname]", CmdPrompt, _UU("CMD_BridgeCreate_PROMPT_HUBNAME"), CmdEvalNotEmpty, NULL},\r
+               {"DEVICE", CmdPrompt, _UU("CMD_BridgeCreate_PROMPT_DEVICE"), CmdEvalNotEmpty, NULL},\r
+               {"TAP", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       t.Active = true;\r
+       StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "DEVICE"));\r
+       StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[hubname]"));\r
+       t.Online = true;\r
+       t.TapMode = GetParamYes(o, "TAP");\r
+\r
+       // RPC 呼び出し\r
+       ret = ScAddLocalBridge(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               c->Write(c, _UU("SM_BRIDGE_INTEL"));\r
+               c->Write(c, L"");\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ローカル ブリッジ接続の削除\r
+UINT PsBridgeDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_LOCALBRIDGE t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[hubname]", CmdPrompt, _UU("CMD_BridgeDelete_PROMPT_HUBNAME"), CmdEvalNotEmpty, NULL},\r
+               {"DEVICE", CmdPrompt, _UU("CMD_BridgeDelete_PROMPT_DEVICE"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.DeviceName, sizeof(t.DeviceName), GetParamStr(o, "DEVICE"));\r
+       StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[hubname]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDeleteLocalBridge(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// サーバーの機能・能力一覧の取得\r
+UINT PsCaps(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       CAPSLIST *t;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       t = ScGetCapsEx(ps->Rpc);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               UINT i;\r
+               CT *ct;\r
+\r
+               ct = CtNewStandard();\r
+\r
+               for (i = 0;i < LIST_NUM(t->CapsList);i++)\r
+               {\r
+                       CAPS *c = LIST_DATA(t->CapsList, i);\r
+                       wchar_t title[MAX_SIZE];\r
+                       char name[256];\r
+\r
+                       Format(name, sizeof(name), "CT_%s", c->Name);\r
+\r
+                       UniStrCpy(title, sizeof(title), _UU(name));\r
+\r
+                       if (UniIsEmptyStr(title))\r
+                       {\r
+                               UniFormat(title, sizeof(title), L"%S", (StrLen(c->Name) >= 2) ? c->Name + 2 : c->Name);\r
+                       }\r
+\r
+                       if (StartWith(c->Name, "b_"))\r
+                       {\r
+                               bool icon_pass = c->Value == 0 ? false : true;\r
+                               if (StrCmpi(c->Name, "b_must_install_pcap") == 0)\r
+                               {\r
+                                       // WinPcap の項目のみ反転する\r
+                                       icon_pass = !icon_pass;\r
+                               }\r
+                               CtInsert(ct, title, c->Value == 0 ? _UU("CAPS_NO") : _UU("CAPS_YES"));\r
+                       }\r
+                       else\r
+                       {\r
+                               wchar_t str[64];\r
+                               UniToStru(str, c->Value);\r
+                               CtInsert(ct, title, str);\r
+                       }\r
+               }\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeCapsList(t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// VPN Server サービスの再起動\r
+UINT PsReboot(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_TEST t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"RESETCONFIG", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       t.IntValue = GetParamYes(o, "RESETCONFIG") ? 1 : 0;\r
+\r
+       // RPC 呼び出し\r
+       ret = ScRebootServer(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcTest(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// VPN Server の現在のコンフィグレーションの取得\r
+UINT PsConfigGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CONFIG t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[path]", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetConfig(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               char *filename = GetParamStr(o, "[path]");\r
+\r
+               if (IsEmptyStr(filename))\r
+               {\r
+                       // 画面に表示\r
+                       wchar_t tmp[MAX_SIZE];\r
+                       UINT buf_size;\r
+                       wchar_t *buf;\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CMD_ConfigGet_FILENAME"), t.FileName,\r
+                               StrLen(t.FileData));\r
+                       c->Write(c, tmp);\r
+                       c->Write(c, L"");\r
+\r
+                       buf_size = CalcUtf8ToUni((BYTE *)t.FileData, StrLen(t.FileData));\r
+                       buf = ZeroMalloc(buf_size + 32);\r
+\r
+                       Utf8ToUni(buf, buf_size, (BYTE *)t.FileData, StrLen(t.FileData));\r
+\r
+                       c->Write(c, buf);\r
+                       c->Write(c, L"");\r
+\r
+                       Free(buf);\r
+               }\r
+               else\r
+               {\r
+                       // ファイルに保存\r
+                       IO *io = FileCreate(filename);\r
+\r
+                       if (io == NULL)\r
+                       {\r
+                               c->Write(c, _UU("CMD_ConfigGet_FILE_SAVE_FAILED"));\r
+\r
+                               ret = ERR_INTERNAL_ERROR;\r
+                       }\r
+                       else\r
+                       {\r
+                               FileWrite(io, t.FileData, StrLen(t.FileData));\r
+                               FileClose(io);\r
+                       }\r
+               }\r
+       }\r
+\r
+       FreeRpcConfig(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// VPN Server へのコンフィグレーションの書き込み\r
+UINT PsConfigSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CONFIG t;\r
+       char *filename;\r
+       BUF *buf;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[path]", CmdPrompt, _UU("CMD_ConfigSet_PROMPT_PATH"), CmdEvalIsFile, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       filename = GetParamStr(o, "[path]");\r
+\r
+       buf = ReadDump(filename);\r
+       if (buf == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_ConfigSet_FILE_LOAD_FAILED"));\r
+       }\r
+       else\r
+       {\r
+               Zero(&t, sizeof(t));\r
+\r
+               t.FileData = ZeroMalloc(buf->Size + 1);\r
+               Copy(t.FileData, buf->Buf, buf->Size);\r
+               FreeBuf(buf);\r
+\r
+               // RPC 呼び出し\r
+               ret = ScSetConfig(ps->Rpc, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcConfig(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想レイヤ 3 スイッチ一覧の取得\r
+UINT PsRouterList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_L3SW t;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumL3Switch(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct = CtNew();\r
+               UINT i;\r
+\r
+               CtInsertColumn(ct, _UU("SM_L3_SW_COLUMN1"), false);\r
+               CtInsertColumn(ct, _UU("SM_L3_SW_COLUMN2"), false);\r
+               CtInsertColumn(ct, _UU("SM_L3_SW_COLUMN3"), true);\r
+               CtInsertColumn(ct, _UU("SM_L3_SW_COLUMN4"), true);\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       RPC_ENUM_L3SW_ITEM *e = &t.Items[i];\r
+                       wchar_t tmp1[MAX_SIZE], *tmp2, tmp3[64], tmp4[64];\r
+\r
+                       StrToUni(tmp1, sizeof(tmp1), e->Name);\r
+                       if (e->Active == false)\r
+                       {\r
+                               tmp2 = _UU("SM_L3_SW_ST_F_F");\r
+                       }\r
+                       else if (e->Online == false)\r
+                       {\r
+                               tmp2 = _UU("SM_L3_SW_ST_T_F");\r
+                       }\r
+                       else\r
+                       {\r
+                               tmp2 = _UU("SM_L3_SW_ST_T_T");\r
+                       }\r
+                       UniToStru(tmp3, e->NumInterfaces);\r
+                       UniToStru(tmp4, e->NumTables);\r
+\r
+                       CtInsert(ct,\r
+                               tmp1, tmp2, tmp3, tmp4);\r
+               }\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeRpcEnumL3Sw(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 新しい仮想レイヤ 3 スイッチの定義\r
+UINT PsRouterAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_L3SW t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_RouterAdd_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScAddL3Switch(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想レイヤ 3 スイッチの削除\r
+UINT PsRouterDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_L3SW t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_RouterDelete_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDelL3Switch(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想レイヤ 3 スイッチの動作の開始\r
+UINT PsRouterStart(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_L3SW t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_RouterStart_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScStartL3Switch(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想レイヤ 3 スイッチの動作の停止\r
+UINT PsRouterStop(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_L3SW t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_RouterStop_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScStopL3Switch(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想レイヤ 3 スイッチに登録されているインターフェイス一覧の取得\r
+UINT PsRouterIfList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_L3IF t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_RouterIfList_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumL3If(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               UINT i;\r
+               wchar_t tmp1[MAX_SIZE];\r
+               wchar_t tmp2[MAX_SIZE];\r
+               wchar_t tmp3[MAX_SIZE];\r
+               CT *ct = CtNew();\r
+\r
+               CtInsertColumn(ct, _UU("SM_L3_SW_IF_COLUMN1"), false);\r
+               CtInsertColumn(ct, _UU("SM_L3_SW_IF_COLUMN2"), false);\r
+               CtInsertColumn(ct, _UU("SM_L3_SW_IF_COLUMN3"), false);\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       RPC_L3IF *e = &t.Items[i];\r
+\r
+                       IPToUniStr32(tmp1, sizeof(tmp1), e->IpAddress);\r
+                       IPToUniStr32(tmp2, sizeof(tmp2), e->SubnetMask);\r
+                       StrToUni(tmp3, sizeof(tmp3), e->HubName);\r
+\r
+                       CtInsert(ct, tmp1, tmp2, tmp3);\r
+               }\r
+\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeRpcEnumL3If(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// IP アドレスとマスクの評価\r
+bool CmdEvalIpAndMask4(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       UINT ip, mask;\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       UniToStr(tmp, sizeof(tmp), str);\r
+\r
+       if (ParseIpAndMask4(tmp, &ip, &mask) == false)\r
+       {\r
+               c->Write(c, _UU("CMD_PARSE_IP_MASK_ERROR_1"));\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+bool CmdEvalIpAndMask6(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       IP ip, mask;\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       UniToStr(tmp, sizeof(tmp), str);\r
+\r
+       if (ParseIpAndMask6(tmp, &ip, &mask) == false)\r
+       {\r
+               c->Write(c, _UU("CMD_PARSE_IP_MASK_ERROR_1_6"));\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+bool CmdEvalIpAndMask46(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       TOKEN_LIST *t;\r
+       bool ret = false;\r
+\r
+       Zero(tmp, sizeof(tmp));\r
+       UniToStr(tmp, sizeof(tmp), str);\r
+\r
+       t = ParseToken(tmp, "/");\r
+       if (t == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (t->NumTokens >= 1)\r
+       {\r
+               Trim(t->Token[0]);\r
+\r
+               if (IsIpStr4(t->Token[0]))\r
+               {\r
+                       ret = CmdEvalIpAndMask4(c, str, param);\r
+               }\r
+               else\r
+               {\r
+                       ret = CmdEvalIpAndMask6(c, str, param);\r
+               }\r
+       }\r
+\r
+       FreeToken(t);\r
+\r
+       return ret;\r
+}\r
+\r
+// ネットワークアドレスとサブネットマスクの評価\r
+bool CmdEvalNetworkAndSubnetMask4(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       UINT ip, mask;\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       UniToStr(tmp, sizeof(tmp), str);\r
+\r
+       if (ParseIpAndSubnetMask4(tmp, &ip, &mask) == false)\r
+       {\r
+               c->Write(c, _UU("CMD_PARSE_IP_SUBNET_ERROR_1"));\r
+               return false;\r
+       }\r
+\r
+       if (IsNetworkAddress32(ip, mask) == false)\r
+       {\r
+               c->Write(c, _UU("CMD_PARSE_IP_SUBNET_ERROR_2"));\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+bool CmdEvalNetworkAndSubnetMask6(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       IP ip, mask;\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       UniToStr(tmp, sizeof(tmp), str);\r
+\r
+       if (ParseIpAndSubnetMask6(tmp, &ip, &mask) == false)\r
+       {\r
+               c->Write(c, _UU("CMD_PARSE_IP_SUBNET_ERROR_1_6"));\r
+               return false;\r
+       }\r
+\r
+       if (IsNetworkPrefixAddress6(&ip, &mask) == false)\r
+       {\r
+               c->Write(c, _UU("CMD_PARSE_IP_SUBNET_ERROR_3"));\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+bool CmdEvalNetworkAndSubnetMask46(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       TOKEN_LIST *t;\r
+       bool ret = false;\r
+\r
+       Zero(tmp, sizeof(tmp));\r
+       UniToStr(tmp, sizeof(tmp), str);\r
+\r
+       t = ParseToken(tmp, "/");\r
+       if (t == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (t->NumTokens >= 1)\r
+       {\r
+               Trim(t->Token[0]);\r
+\r
+               if (IsIpStr4(t->Token[0]))\r
+               {\r
+                       ret = CmdEvalNetworkAndSubnetMask4(c, str, param);\r
+               }\r
+               else\r
+               {\r
+                       ret = CmdEvalNetworkAndSubnetMask6(c, str, param);\r
+               }\r
+       }\r
+\r
+       FreeToken(t);\r
+\r
+       return ret;\r
+}\r
+\r
+// IP アドレスとサブネットマスクの評価\r
+bool CmdEvalHostAndSubnetMask4(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       UniToStr(tmp, sizeof(tmp), str);\r
+\r
+       if (ParseIpAndSubnetMask4(tmp, NULL, NULL) == false)\r
+       {\r
+               c->Write(c, _UU("CMD_PARSE_IP_SUBNET_ERROR_1"));\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// 仮想レイヤ 3 スイッチへの仮想インターフェイスの追加\r
+UINT PsRouterIfAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_L3IF t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_RouterIfAdd_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"HUB", CmdPrompt, _UU("CMD_RouterIfAdd_PROMPT_HUB"), CmdEvalNotEmpty, NULL},\r
+               {"IP", CmdPrompt, _UU("CMD_RouterIfAdd_PROMPT_IP"), CmdEvalHostAndSubnetMask4, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+       ParseIpAndSubnetMask4(GetParamStr(o, "IP"), &t.IpAddress, &t.SubnetMask);\r
+       StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "HUB"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScAddL3If(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想レイヤ 3 スイッチの仮想インターフェイスの削除\r
+UINT PsRouterIfDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_L3IF t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_RouterIfAdd_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"HUB", CmdPrompt, _UU("CMD_RouterIfAdd_PROMPT_HUB"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+       StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "HUB"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDelL3If(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想レイヤ 3 スイッチのルーティング テーブル一覧の取得\r
+UINT PsRouterTableList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_L3TABLE t;\r
+       CT *ct;\r
+       wchar_t tmp1[MAX_SIZE];\r
+       wchar_t tmp2[MAX_SIZE];\r
+       wchar_t tmp3[MAX_SIZE];\r
+       wchar_t tmp4[MAX_SIZE];\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_RouterTableList_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumL3Table(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               UINT i;\r
+\r
+               ct = CtNew();\r
+\r
+               CtInsertColumn(ct, _UU("SM_L3_SW_TABLE_COLUMN1"), false);\r
+               CtInsertColumn(ct, _UU("SM_L3_SW_TABLE_COLUMN2"), false);\r
+               CtInsertColumn(ct, _UU("SM_L3_SW_TABLE_COLUMN3"), false);\r
+               CtInsertColumn(ct, _UU("SM_L3_SW_TABLE_COLUMN4"), true);\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       RPC_L3TABLE *e = &t.Items[i];\r
+\r
+                       IPToUniStr32(tmp1, sizeof(tmp1), e->NetworkAddress);\r
+                       IPToUniStr32(tmp2, sizeof(tmp2), e->SubnetMask);\r
+                       IPToUniStr32(tmp3, sizeof(tmp3), e->GatewayAddress);\r
+                       UniToStru(tmp4, e->Metric);\r
+\r
+                       CtInsert(ct, tmp1, tmp2, tmp3, tmp4);\r
+               }\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeRpcEnumL3Table(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想レイヤ 3 スイッチへのルーティング テーブル エントリの追加\r
+UINT PsRouterTableAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_L3TABLE t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"NETWORK", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_NETWORK"), CmdEvalNetworkAndSubnetMask4, NULL},\r
+               {"GATEWAY", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_GATEWAY"), CmdEvalIp, NULL},\r
+               {"METRIC", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_METRIC"), CmdEvalInt1, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+       ParseIpAndSubnetMask4(GetParamStr(o, "NETWORK"), &t.NetworkAddress, &t.SubnetMask);\r
+       t.Metric = GetParamInt(o, "METRIC");\r
+       t.GatewayAddress = StrToIP32(GetParamStr(o, "GATEWAY"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScAddL3Table(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想レイヤ 3 スイッチのルーティング テーブル エントリの削除\r
+UINT PsRouterTableDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_L3TABLE t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"NETWORK", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_NETWORK"), CmdEvalNetworkAndSubnetMask4, NULL},\r
+               {"GATEWAY", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_GATEWAY"), CmdEvalIp, NULL},\r
+               {"METRIC", CmdPrompt, _UU("CMD_RouterTableAdd_PROMPT_METRIC"), CmdEvalInt1, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+       ParseIpAndSubnetMask4(GetParamStr(o, "NETWORK"), &t.NetworkAddress, &t.SubnetMask);\r
+       t.Metric = GetParamInt(o, "METRIC");\r
+       t.GatewayAddress = StrToIP32(GetParamStr(o, "GATEWAY"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDelL3Table(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ログ ファイル一覧の取得\r
+UINT PsLogFileList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_LOG_FILE t;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       c->Write(c, _UU("CMD_LogFileList_START"));\r
+       c->Write(c, L"");\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumLogFile(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               UINT i;\r
+               wchar_t tmp[MAX_SIZE];\r
+               CT *ct;\r
+\r
+               UniFormat(tmp, sizeof(tmp), _UU("CMD_LogFileList_NUM_LOGS"), t.NumItem);\r
+               c->Write(c, tmp);\r
+\r
+               ct = CtNew();\r
+\r
+               CtInsertColumn(ct, _UU("SM_LOG_FILE_COLUMN_1"), false);\r
+               CtInsertColumn(ct, _UU("SM_LOG_FILE_COLUMN_2"), true);\r
+               CtInsertColumn(ct, _UU("SM_LOG_FILE_COLUMN_3"), false);\r
+               CtInsertColumn(ct, _UU("SM_LOG_FILE_COLUMN_4"), false);\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       RPC_ENUM_LOG_FILE_ITEM *e = &t.Items[i];\r
+                       wchar_t tmp1[MAX_PATH], tmp2[128], tmp3[128], tmp4[MAX_HOST_NAME_LEN + 1];\r
+                       char tmp[MAX_SIZE];\r
+\r
+                       StrToUni(tmp1, sizeof(tmp1), e->FilePath);\r
+\r
+                       ToStrByte(tmp, sizeof(tmp), e->FileSize);\r
+                       StrToUni(tmp2, sizeof(tmp2), tmp);\r
+\r
+                       GetDateTimeStr64Uni(tmp3, sizeof(tmp3), SystemToLocal64(e->UpdatedTime));\r
+\r
+                       StrToUni(tmp4, sizeof(tmp4), e->ServerName);\r
+\r
+                       CtInsert(ct, tmp1, tmp2, tmp3, tmp4);\r
+               }\r
+\r
+               CtFreeEx(ct, c, true);\r
+       }\r
+\r
+       FreeRpcEnumLogFile(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ログ ファイルのダウンロード\r
+UINT PsLogFileGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       BUF *buf;\r
+       char *filename = NULL;\r
+       char *server_name;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_LogFileGet_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"SERVER", NULL, NULL, NULL, NULL},\r
+               {"SAVEPATH", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       filename = GetParamStr(o, "SAVE");\r
+\r
+       c->Write(c, _UU("CMD_LogFileGet_START"));\r
+\r
+       server_name = GetParamStr(o, "SERVER");\r
+\r
+       buf = DownloadFileFromServer(ps->Rpc, server_name,\r
+               GetParamStr(o, "[name]"), 0, NULL, NULL);\r
+\r
+       if (buf == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_LogFileGet_FAILED"));\r
+\r
+               ret = ERR_INTERNAL_ERROR;\r
+       }\r
+       else\r
+       {\r
+               if (IsEmptyStr(filename) == false)\r
+               {\r
+                       // ファイルに保存\r
+                       if (DumpBuf(buf, filename) == false)\r
+                       {\r
+                               ret = ERR_INTERNAL_ERROR;\r
+                               c->Write(c, _UU("CMD_LogFileGet_SAVE_FAILED"));\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       // 画面に表示\r
+                       wchar_t tmp[MAX_SIZE];\r
+                       UINT buf_size;\r
+                       wchar_t *uni_buf;\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CMD_LogFileGet_FILESIZE"),\r
+                               buf->Size);\r
+                       c->Write(c, tmp);\r
+                       c->Write(c, L"");\r
+\r
+                       buf_size = CalcUtf8ToUni((BYTE *)buf->Buf, buf->Size);\r
+                       uni_buf = ZeroMalloc(buf_size + 32);\r
+\r
+                       Utf8ToUni(uni_buf, buf_size, (BYTE *)buf->Buf, buf->Size);\r
+\r
+                       c->Write(c, uni_buf);\r
+                       c->Write(c, L"");\r
+\r
+                       Free(uni_buf);\r
+               }\r
+\r
+               FreeBuf(buf);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 新しい仮想 HUB の作成\r
+UINT PsHubCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_HUB t;\r
+       char *pass = "";\r
+       UINT hub_type = HUB_TYPE_STANDALONE;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_HubCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"PASSWORD", CmdPromptChoosePassword, NULL, NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+       else\r
+       {\r
+               RPC_SERVER_INFO t;\r
+               Zero(&t, sizeof(t));\r
+               if (ScGetServerInfo(ps->Rpc, &t) == ERR_NO_ERROR)\r
+               {\r
+                       if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+                       {\r
+                               hub_type = HUB_TYPE_FARM_DYNAMIC;\r
+                       }\r
+                       FreeRpcServerInfo(&t);\r
+               }\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));\r
+       t.HubType = hub_type;\r
+\r
+       if (IsEmptyStr(GetParamStr(o, "PASSWORD")) == false)\r
+       {\r
+               pass = GetParamStr(o, "PASSWORD");\r
+       }\r
+\r
+       Hash(t.HashedPassword, pass, StrLen(pass), true);\r
+       HashPassword(t.SecurePassword, ADMINISTRATOR_USERNAME, pass);\r
+       t.Online = true;\r
+\r
+       // RPC 呼び出し\r
+       ret = ScCreateHub(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 新しい仮想 HUB の作成 (ダイナミックモード)\r
+UINT PsHubCreateDynamic(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_HUB t;\r
+       char *pass = "";\r
+       UINT hub_type = HUB_TYPE_FARM_DYNAMIC;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_HubCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"PASSWORD", CmdPromptChoosePassword, NULL, NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));\r
+       t.HubType = hub_type;\r
+\r
+       if (IsEmptyStr(GetParamStr(o, "PASSWORD")) == false)\r
+       {\r
+               pass = GetParamStr(o, "PASSWORD");\r
+       }\r
+\r
+       Hash(t.HashedPassword, pass, StrLen(pass), true);\r
+       HashPassword(t.SecurePassword, ADMINISTRATOR_USERNAME, pass);\r
+       t.Online = true;\r
+\r
+       // RPC 呼び出し\r
+       ret = ScCreateHub(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 新しい仮想 HUB の作成 (スタティックモード)\r
+UINT PsHubCreateStatic(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_HUB t;\r
+       char *pass = "";\r
+       UINT hub_type = HUB_TYPE_FARM_STATIC;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_HubCreate_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"PASSWORD", CmdPromptChoosePassword, NULL, NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));\r
+       t.HubType = hub_type;\r
+\r
+       if (IsEmptyStr(GetParamStr(o, "PASSWORD")) == false)\r
+       {\r
+               pass = GetParamStr(o, "PASSWORD");\r
+       }\r
+\r
+       Hash(t.HashedPassword, pass, StrLen(pass), true);\r
+       HashPassword(t.SecurePassword, ADMINISTRATOR_USERNAME, pass);\r
+       t.Online = true;\r
+\r
+       // RPC 呼び出し\r
+       ret = ScCreateHub(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB の削除\r
+UINT PsHubDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_DELETE_HUB t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_HubDelete_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDeleteHub(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB をスタティックにする\r
+UINT PsHubSetStatic(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_HUB t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_HubChange_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));\r
+\r
+       // まず現在の設定を取得する\r
+       ret = ScGetHub(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       // 設定を変更する\r
+       StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));\r
+       t.HubType = HUB_TYPE_FARM_STATIC;\r
+\r
+       // 書き込む\r
+       ret = ScSetHub(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB の種類をダイナミック仮想 HUB に変更\r
+UINT PsHubSetDynamic(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_HUB t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_HubChange_PROMPT_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));\r
+\r
+       // まず現在の設定を取得する\r
+       ret = ScGetHub(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       // 設定を変更する\r
+       StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));\r
+       t.HubType = HUB_TYPE_FARM_DYNAMIC;\r
+\r
+       // 書き込む\r
+       ret = ScSetHub(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB の一覧の取得\r
+UINT PsHubList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_HUB t;\r
+       UINT i;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumHub(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct = CtNew();\r
+\r
+               CtInsertColumn(ct, _UU("SM_HUB_COLUMN_1"), false);\r
+               CtInsertColumn(ct, _UU("SM_HUB_COLUMN_2"), false);\r
+               CtInsertColumn(ct, _UU("SM_HUB_COLUMN_3"), false);\r
+               CtInsertColumn(ct, _UU("SM_HUB_COLUMN_4"), false);\r
+               CtInsertColumn(ct, _UU("SM_HUB_COLUMN_5"), false);\r
+               CtInsertColumn(ct, _UU("SM_HUB_COLUMN_6"), false);\r
+               CtInsertColumn(ct, _UU("SM_HUB_COLUMN_7"), false);\r
+               CtInsertColumn(ct, _UU("SM_HUB_COLUMN_8"), false);\r
+               CtInsertColumn(ct, _UU("SM_HUB_COLUMN_9"), false);\r
+               CtInsertColumn(ct, _UU("SM_HUB_COLUMN_10"), false);\r
+               CtInsertColumn(ct, _UU("SM_HUB_COLUMN_11"), false);\r
+\r
+               for (i = 0;i < t.NumHub;i++)\r
+               {\r
+                       RPC_ENUM_HUB_ITEM *e = &t.Hubs[i];\r
+                       wchar_t name[MAX_HUBNAME_LEN + 1];\r
+                       wchar_t s1[64], s2[64], s3[64], s4[64], s5[64];\r
+                       wchar_t s6[64], s7[128], s8[128];\r
+                       UniToStru(s1, e->NumUsers);\r
+                       UniToStru(s2, e->NumGroups);\r
+                       UniToStru(s3, e->NumSessions);\r
+                       UniToStru(s4, e->NumMacTables);\r
+                       UniToStru(s5, e->NumIpTables);\r
+\r
+                       UniToStru(s6, e->NumLogin);\r
+\r
+                       if (e->LastLoginTime != 0)\r
+                       {\r
+                               GetDateTimeStr64Uni(s7, sizeof(s7), SystemToLocal64(e->LastLoginTime));\r
+                       }\r
+                       else\r
+                       {\r
+                               UniStrCpy(s7, sizeof(s7), _UU("COMMON_UNKNOWN"));\r
+                       }\r
+\r
+                       if (e->LastCommTime != 0)\r
+                       {\r
+                               GetDateTimeStr64Uni(s8, sizeof(s8), SystemToLocal64(e->LastCommTime));\r
+                       }\r
+                       else\r
+                       {\r
+                               UniStrCpy(s8, sizeof(s8), _UU("COMMON_UNKNOWN"));\r
+                       }\r
+\r
+                       StrToUni(name, sizeof(name), e->HubName);\r
+\r
+                       CtInsert(ct,\r
+                               name,\r
+                               e->Online ? _UU("SM_HUB_ONLINE") : _UU("SM_HUB_OFFLINE"),\r
+                               GetHubTypeStr(e->HubType),\r
+                               s1, s2, s3, s4, s5, s6, s7, s8);\r
+               }\r
+\r
+               CtFreeEx(ct, c, true);\r
+       }\r
+\r
+       FreeRpcEnumHub(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 管理する仮想 HUB の選択\r
+UINT PsHub(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_HUB_STATUS t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (IsEmptyStr(GetParamStr(o, "[name]")) == false)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               Zero(&t, sizeof(t));\r
+\r
+               // 指定した仮想 HUB にアクセスできるかどうか調べる\r
+               StrCpy(t.HubName, sizeof(t.HubName), GetParamStr(o, "[name]"));\r
+\r
+               // RPC 呼び出し\r
+               ret = ScGetHubStatus(ps->Rpc, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               // 選択を変更する\r
+               if (ps->HubName != NULL)\r
+               {\r
+                       Free(ps->HubName);\r
+               }\r
+               ps->HubName = CopyStr(t.HubName);\r
+\r
+               UniFormat(tmp, sizeof(tmp), _UU("CMD_Hub_Selected"), t.HubName);\r
+               c->Write(c, tmp);\r
+       }\r
+       else\r
+       {\r
+               // 選択を解除する\r
+               if (ps->HubName != NULL)\r
+               {\r
+                       c->Write(c, _UU("CMD_Hub_Unselected"));\r
+                       Free(ps->HubName);\r
+               }\r
+               ps->HubName = NULL;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB をオンラインにする\r
+UINT PsOnline(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_HUB_ONLINE t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.Online = true;\r
+\r
+       // RPC 呼び出し\r
+       ret = ScSetHubOnline(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB をオフラインにする\r
+UINT PsOffline(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_HUB_ONLINE t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.Online = false;\r
+\r
+       // RPC 呼び出し\r
+       ret = ScSetHubOnline(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB の最大同時接続セッション数を設定する\r
+UINT PsSetMaxSession(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_HUB t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[max_session]", CmdPrompt, _UU("CMD_SetMaxSession_Prompt"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // 現在の仮想 HUB の設定を取得\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       ret = ScGetHub(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       t.HubOption.MaxSession = GetParamInt(o, "[max_session]");\r
+\r
+       // 仮想 HUB の設定を書き込み\r
+       ret = ScSetHub(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB の管理パスワードを設定する\r
+UINT PsSetHubPassword(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_HUB t;\r
+       char *pw;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[password]", CmdPromptChoosePassword, NULL, NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // 現在の仮想 HUB の設定を取得\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       ret = ScGetHub(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       // 設定の変更\r
+       pw = GetParamStr(o, "[password]");\r
+       HashPassword(t.SecurePassword, ADMINISTRATOR_USERNAME, pw);\r
+       Hash(t.HashedPassword, pw, StrLen(pw), true);\r
+\r
+       // 仮想 HUB の設定を書き込み\r
+       ret = ScSetHub(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB の匿名ユーザーへの列挙の許可設定\r
+UINT PsSetEnumAllow(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_HUB t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // 現在の仮想 HUB の設定を取得\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       ret = ScGetHub(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       t.HubOption.NoEnum = false;\r
+\r
+       // 仮想 HUB の設定を書き込み\r
+       ret = ScSetHub(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB の匿名ユーザーへの列挙の禁止設定\r
+UINT PsSetEnumDeny(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_HUB t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // 現在の仮想 HUB の設定を取得\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       ret = ScGetHub(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       t.HubOption.NoEnum = true;\r
+\r
+       // 仮想 HUB の設定を書き込み\r
+       ret = ScSetHub(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB のオプション設定の取得\r
+UINT PsOptionsGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_HUB t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetHub(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct;\r
+               wchar_t tmp[MAX_SIZE];\r
+\r
+               UniFormat(tmp, sizeof(tmp), _UU("CMD_OptionsGet_TITLE"), ps->HubName);\r
+               c->Write(c, tmp);\r
+\r
+               // 設定の表示\r
+               ct = CtNewStandard();\r
+\r
+               CtInsert(ct, _UU("CMD_OptionsGet_ENUM"),\r
+                       t.HubOption.NoEnum ? _UU("CMD_MSG_DENY") : _UU("CMD_MSG_ALLOW"));\r
+\r
+               if (t.HubOption.MaxSession == 0)\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("CMD_MSG_INFINITE"));\r
+               }\r
+               else\r
+               {\r
+                       UniToStru(tmp, t.HubOption.MaxSession);\r
+               }\r
+               CtInsert(ct, _UU("CMD_OptionsGet_MAXSESSIONS"), tmp);\r
+\r
+               CtInsert(ct, _UU("CMD_OptionsGet_STATUS"), t.Online ? _UU("SM_HUB_ONLINE") : _UU("SM_HUB_OFFLINE"));\r
+\r
+               CtInsert(ct, _UU("CMD_OptionsGet_TYPE"), GetHubTypeStr(t.HubType));\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザー認証に使用する Radius サーバーの設定\r
+UINT PsRadiusServerSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_RADIUS t;\r
+       char *host;\r
+       UINT port;\r
+       // 指定できるパラメータ リスト\r
+       CMD_EVAL_MIN_MAX minmax =\r
+       {\r
+               "CMD_RadiusServerSet_EVAL_NUMINTERVAL", RADIUS_RETRY_INTERVAL, RADIUS_RETRY_TIMEOUT,\r
+       };\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[server_name:port]", CmdPrompt, _UU("CMD_RadiusServerSet_Prompt_Host"), CmdEvalNotEmpty, NULL},\r
+               {"SECRET", CmdPromptChoosePassword, _UU("CMD_RadiusServerSet_Prompt_Secret"), NULL, NULL},\r
+               {"RETRY_INTERVAL", CmdPrompt, _UU("CMD_RadiusServerSet_Prompt_RetryInterval"), CmdEvalMinMax, &minmax},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (ParseHostPort(GetParamStr(o, "[server_name:port]"), &host, &port, 1812))\r
+       {\r
+               Zero(&t, sizeof(t));\r
+\r
+               StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+               t.RadiusPort = port;\r
+               StrCpy(t.RadiusServerName, sizeof(t.RadiusServerName), host);\r
+               StrCpy(t.RadiusSecret, sizeof(t.RadiusSecret), GetParamStr(o, "SECRET"));\r
+               t.RadiusRetryInterval = GetParamInt(o, "RETRY_INTERVAL");\r
+\r
+               Free(host);\r
+\r
+               // RPC 呼び出し\r
+               ret = ScSetHubRadius(ps->Rpc, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザー認証に使用する Radius サーバー設定の削除\r
+UINT PsRadiusServerDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_RADIUS t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.RadiusPort = 1812;\r
+\r
+       // RPC 呼び出し\r
+       ret = ScSetHubRadius(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザー認証に使用する Radius サーバー設定の取得\r
+UINT PsRadiusServerGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_RADIUS t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetHubRadius(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct;\r
+               wchar_t tmp[MAX_SIZE];\r
+\r
+               ct = CtNewStandard();\r
+\r
+               if (IsEmptyStr(t.RadiusServerName))\r
+               {\r
+                       CtInsert(ct, _UU("CMD_RadiusServerGet_STATUS"), _UU("CMD_MSG_DISABLE"));\r
+               }\r
+               else\r
+               {\r
+                       CtInsert(ct, _UU("CMD_RadiusServerGet_STATUS"), _UU("CMD_MSG_ENABLE"));\r
+\r
+                       StrToUni(tmp, sizeof(tmp), t.RadiusServerName);\r
+                       CtInsert(ct, _UU("CMD_RadiusServerGet_HOST"), tmp);\r
+\r
+                       UniToStri(tmp, t.RadiusPort);\r
+                       CtInsert(ct, _UU("CMD_RadiusServerGet_PORT"), tmp);\r
+\r
+                       StrToUni(tmp, sizeof(tmp), t.RadiusSecret);\r
+                       CtInsert(ct, _UU("CMD_RadiusServerGet_SECRET"), tmp);\r
+\r
+                       UniToStri(tmp, t.RadiusRetryInterval);\r
+                       CtInsert(ct, _UU("CMD_RadiusServerGet_RetryInterval"), tmp);\r
+               }\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB の現在の状況の取得\r
+UINT PsStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_HUB_STATUS t;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetHubStatus(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct = CtNewStandard();\r
+               wchar_t *s;\r
+               wchar_t tmp[MAX_SIZE];\r
+\r
+               // HUB 名\r
+               s = CopyStrToUni(t.HubName);\r
+               CtInsert(ct, _UU("SM_HUB_STATUS_HUBNAME"), s);\r
+               Free(s);\r
+\r
+               // オンライン\r
+               CtInsert(ct, _UU("SM_HUB_STATUS_ONLINE"),\r
+                       t.Online ? _UU("SM_HUB_ONLINE") : _UU("SM_HUB_OFFLINE"));\r
+\r
+               // HUB の種類\r
+               CtInsert(ct, _UU("SM_HUB_TYPE"),\r
+                       GetHubTypeStr(t.HubType));\r
+\r
+               if (t.HubType == HUB_TYPE_STANDALONE)\r
+               {\r
+                       // SecureNAT の有効/無効\r
+                       CtInsert(ct, _UU("SM_HUB_SECURE_NAT"),\r
+                               t.SecureNATEnabled ? _UU("SM_HUB_SECURE_NAT_YES") : _UU("SM_HUB_SECURE_NAT_NO"));\r
+               }\r
+\r
+               // その他の値\r
+               UniToStru(tmp, t.NumSessions);\r
+               CtInsert(ct, _UU("SM_HUB_NUM_SESSIONS"), tmp);\r
+\r
+               if (t.NumSessionsClient != 0 || t.NumSessionsBridge != 0)\r
+               {\r
+                       UniToStru(tmp, t.NumSessionsClient);\r
+                       CtInsert(ct, _UU("SM_HUB_NUM_SESSIONS_CLIENT"), tmp);\r
+                       UniToStru(tmp, t.NumSessionsBridge);\r
+                       CtInsert(ct, _UU("SM_HUB_NUM_SESSIONS_BRIDGE"), tmp);\r
+               }\r
+\r
+               UniToStru(tmp, t.NumAccessLists);\r
+               CtInsert(ct, _UU("SM_HUB_NUM_ACCESSES"), tmp);\r
+\r
+               UniToStru(tmp, t.NumUsers);\r
+               CtInsert(ct, _UU("SM_HUB_NUM_USERS"), tmp);\r
+               UniToStru(tmp, t.NumGroups);\r
+               CtInsert(ct, _UU("SM_HUB_NUM_GROUPS"), tmp);\r
+\r
+               UniToStru(tmp, t.NumMacTables);\r
+               CtInsert(ct, _UU("SM_HUB_NUM_MAC_TABLES"), tmp);\r
+               UniToStru(tmp, t.NumIpTables);\r
+               CtInsert(ct, _UU("SM_HUB_NUM_IP_TABLES"), tmp);\r
+\r
+               // 利用状況\r
+               UniToStru(tmp, t.NumLogin);\r
+               CtInsert(ct, _UU("SM_HUB_NUM_LOGIN"), tmp);\r
+\r
+               if (t.LastLoginTime != 0)\r
+               {\r
+                       GetDateTimeStr64Uni(tmp, sizeof(tmp), SystemToLocal64(t.LastLoginTime));\r
+               }\r
+               else\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("COMMON_UNKNOWN"));\r
+               }\r
+               CtInsert(ct, _UU("SM_HUB_LAST_LOGIN_TIME"), tmp);\r
+\r
+               if (t.LastCommTime != 0)\r
+               {\r
+                       GetDateTimeStr64Uni(tmp, sizeof(tmp), SystemToLocal64(t.LastCommTime));\r
+               }\r
+               else\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("COMMON_UNKNOWN"));\r
+               }\r
+               CtInsert(ct, _UU("SM_HUB_LAST_COMM_TIME"), tmp);\r
+\r
+               if (t.CreatedTime != 0)\r
+               {\r
+                       GetDateTimeStr64Uni(tmp, sizeof(tmp), SystemToLocal64(t.CreatedTime));\r
+               }\r
+               else\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("COMMON_UNKNOWN"));\r
+               }\r
+               CtInsert(ct, _UU("SM_HUB_CREATED_TIME"), tmp);\r
+\r
+               // トラフィック情報\r
+               CmdInsertTrafficInfo(ct, &t.Traffic);\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ログ切り替え文字列の取得\r
+wchar_t *GetLogSwitchStr(UINT i)\r
+{\r
+       char tmp[64];\r
+\r
+       Format(tmp, sizeof(tmp), "SM_LOG_SWITCH_%u", i);\r
+\r
+       return _UU(tmp);\r
+}\r
+\r
+// パケットログ名文字列の取得\r
+wchar_t *GetPacketLogNameStr(UINT i)\r
+{\r
+       char tmp[64];\r
+\r
+       Format(tmp, sizeof(tmp), "CMD_Log_%u", i);\r
+\r
+       return _UU(tmp);\r
+}\r
+\r
+// 仮想 HUB のログ保存設定の取得\r
+UINT PsLogGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_HUB_LOG t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetHubLog(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct = CtNewStandard();\r
+\r
+               CtInsert(ct, _UU("CMD_Log_SecurityLog"),\r
+                       t.LogSetting.SaveSecurityLog ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+               if (t.LogSetting.SaveSecurityLog)\r
+               {\r
+                       CtInsert(ct, _UU("CMD_Log_SwitchType"), GetLogSwitchStr(t.LogSetting.SecurityLogSwitchType));\r
+               }\r
+\r
+               CtInsert(ct, L"", L"");\r
+\r
+               CtInsert(ct, _UU("CMD_Log_PacketLog"),\r
+                       t.LogSetting.SavePacketLog ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+               if (t.LogSetting.SavePacketLog)\r
+               {\r
+                       UINT i;\r
+\r
+                       CtInsert(ct, _UU("CMD_Log_SwitchType"), GetLogSwitchStr(t.LogSetting.PacketLogSwitchType));\r
+\r
+                       for (i = 0;i <= 7;i++)\r
+                       {\r
+                               wchar_t *tmp = NULL;\r
+\r
+                               switch (t.LogSetting.PacketLogConfig[i])\r
+                               {\r
+                               case PACKET_LOG_NONE:\r
+                                       tmp = _UU("D_SM_LOG@B_PACKET_0_0");\r
+                                       break;\r
+\r
+                               case PACKET_LOG_HEADER:\r
+                                       tmp = _UU("D_SM_LOG@B_PACKET_0_1");\r
+                                       break;\r
+\r
+                               case PACKET_LOG_ALL:\r
+                                       tmp = _UU("D_SM_LOG@B_PACKET_0_2");\r
+                                       break;\r
+                               }\r
+\r
+                               CtInsert(ct, GetPacketLogNameStr(i),\r
+                                       tmp);\r
+                       }\r
+               }\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// LogEnable コマンド\r
+UINT PsLogEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_HUB_LOG t;\r
+       bool packet_log = false;\r
+       char *tmp;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[security|packet]", CmdPrompt, _UU("CMD_LogEnable_Prompt"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       tmp = GetParamStr(o, "[security|packet]");\r
+\r
+       if (StartWith(tmp, "p"))\r
+       {\r
+               packet_log = true;\r
+       }\r
+       else if (StartWith(tmp, "s") == false)\r
+       {\r
+               c->Write(c, _UU("CMD_LogEnable_Prompt_Error"));\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetHubLog(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       if (packet_log == false)\r
+       {\r
+               t.LogSetting.SaveSecurityLog = true;\r
+       }\r
+       else\r
+       {\r
+               t.LogSetting.SavePacketLog = true;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       ret = ScSetHubLog(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// セキュリティ ログまたはパケット ログの無効化\r
+UINT PsLogDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_HUB_LOG t;\r
+       bool packet_log = false;\r
+       char *tmp;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[security|packet]", CmdPrompt, _UU("CMD_LogEnable_Prompt"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       tmp = GetParamStr(o, "[security|packet]");\r
+\r
+       if (StartWith(tmp, "p"))\r
+       {\r
+               packet_log = true;\r
+       }\r
+       else if (StartWith(tmp, "s") == false)\r
+       {\r
+               c->Write(c, _UU("CMD_LogEnable_Prompt_Error"));\r
+               FreeParamValueList(o);\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetHubLog(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       if (packet_log == false)\r
+       {\r
+               t.LogSetting.SaveSecurityLog = false;\r
+       }\r
+       else\r
+       {\r
+               t.LogSetting.SavePacketLog = false;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       ret = ScSetHubLog(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 文字列をログ切り替え種類に変換\r
+UINT StrToLogSwitchType(char *str)\r
+{\r
+       UINT ret = INFINITE;\r
+       // 引数チェック\r
+       if (str == NULL)\r
+       {\r
+               return INFINITE;\r
+       }\r
+\r
+       if (IsEmptyStr(str) || StartWith("none", str))\r
+       {\r
+               ret = LOG_SWITCH_NO;\r
+       }\r
+       else if (StartWith("second", str))\r
+       {\r
+               ret = LOG_SWITCH_SECOND;\r
+       }\r
+       else if (StartWith("minute", str))\r
+       {\r
+               ret = LOG_SWITCH_MINUTE;\r
+       }\r
+       else if (StartWith("hour", str))\r
+       {\r
+               ret = LOG_SWITCH_HOUR;\r
+       }\r
+       else if (StartWith("day", str))\r
+       {\r
+               ret = LOG_SWITCH_DAY;\r
+       }\r
+       else if (StartWith("month", str))\r
+       {\r
+               ret = LOG_SWITCH_MONTH;\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// ログ ファイルの切り替え周期の設定\r
+UINT PsLogSwitchSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_HUB_LOG t;\r
+       bool packet_log = false;\r
+       char *tmp;\r
+       UINT new_switch_type = 0;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[security|packet]", CmdPrompt, _UU("CMD_LogEnable_Prompt"), CmdEvalNotEmpty, NULL},\r
+               {"SWITCH", CmdPrompt, _UU("CMD_LogSwitchSet_Prompt"), NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       tmp = GetParamStr(o, "[security|packet]");\r
+\r
+       if (StartWith(tmp, "p"))\r
+       {\r
+               packet_log = true;\r
+       }\r
+       else if (StartWith(tmp, "s") == false)\r
+       {\r
+               c->Write(c, _UU("CMD_LogEnable_Prompt_Error"));\r
+               FreeParamValueList(o);\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+       \r
+       new_switch_type = StrToLogSwitchType(GetParamStr(o, "SWITCH"));\r
+\r
+       if (new_switch_type == INFINITE)\r
+       {\r
+               c->Write(c, _UU("CMD_LogEnable_Prompt_Error"));\r
+               FreeParamValueList(o);\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetHubLog(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       if (packet_log == false)\r
+       {\r
+               t.LogSetting.SecurityLogSwitchType = new_switch_type;\r
+       }\r
+       else\r
+       {\r
+               t.LogSetting.PacketLogSwitchType = new_switch_type;\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       ret = ScSetHubLog(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// パケットログのパケットの保存内容の文字列を整数に変換\r
+UINT StrToPacketLogSaveInfoType(char *str)\r
+{\r
+       UINT ret = INFINITE;\r
+       if (str == NULL)\r
+       {\r
+               return INFINITE;\r
+       }\r
+\r
+       if (StartWith("none", str) || IsEmptyStr(str))\r
+       {\r
+               ret = PACKET_LOG_NONE;\r
+       }\r
+       else if (StartWith("header", str))\r
+       {\r
+               ret = PACKET_LOG_HEADER;\r
+       }\r
+       else if (StartWith("full", str) || StartWith("all", str))\r
+       {\r
+               ret = PACKET_LOG_ALL;\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// パケットログのパケットの種類の文字列を整数に変換\r
+UINT StrToPacketLogType(char *str)\r
+{\r
+       UINT ret = INFINITE;\r
+       if (str == NULL || IsEmptyStr(str))\r
+       {\r
+               return INFINITE;\r
+       }\r
+\r
+       if (StartWith("tcpconn", str))\r
+       {\r
+               ret = PACKET_LOG_TCP_CONN;\r
+       }\r
+       else if (StartWith("tcpdata", str))\r
+       {\r
+               ret = PACKET_LOG_TCP;\r
+       }\r
+       else if (StartWith("dhcp", str))\r
+       {\r
+               ret = PACKET_LOG_DHCP;\r
+       }\r
+       else if (StartWith("udp", str))\r
+       {\r
+               ret = PACKET_LOG_UDP;\r
+       }\r
+       else if (StartWith("icmp", str))\r
+       {\r
+               ret = PACKET_LOG_ICMP;\r
+       }\r
+       else if (StartWith("ip", str))\r
+       {\r
+               ret = PACKET_LOG_IP;\r
+       }\r
+       else if (StartWith("arp", str))\r
+       {\r
+               ret = PACKET_LOG_ARP;\r
+       }\r
+       else if (StartWith("ethernet", str))\r
+       {\r
+               ret = PACKET_LOG_ETHERNET;\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+// パケット ログに保存するパケットの種類と保存内容の設定\r
+UINT PsLogPacketSaveType(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_HUB_LOG t;\r
+       bool packet_log = false;\r
+       UINT packet_type = INFINITE;\r
+       UINT packet_save_info_type = INFINITE;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"TYPE", CmdPrompt, _UU("CMD_LogPacketSaveType_Prompt_TYPE"), NULL, NULL},\r
+               {"SAVE", CmdPrompt, _UU("CMD_LogPacketSaveType_Prompt_SAVE"), NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+       \r
+       packet_type = StrToPacketLogType(GetParamStr(o, "TYPE"));\r
+       packet_save_info_type = StrToPacketLogSaveInfoType(GetParamStr(o, "SAVE"));\r
+\r
+       if (packet_type == INFINITE || packet_save_info_type == INFINITE)\r
+       {\r
+               c->Write(c, _UU("CMD_LogEnable_Prompt_Error"));\r
+               FreeParamValueList(o);\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetHubLog(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       t.LogSetting.PacketLogConfig[packet_type] = packet_save_info_type;\r
+\r
+       // RPC 呼び出し\r
+       ret = ScSetHubLog(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 信頼する証明機関の証明書一覧の取得\r
+UINT PsCAList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_HUB_ENUM_CA t;\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumCa(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               UINT i;\r
+               CT *ct = CtNewStandard();\r
+\r
+               for (i = 0;i < t.NumCa;i++)\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+                       wchar_t tmp2[64];\r
+                       RPC_HUB_ENUM_CA_ITEM *e = &t.Ca[i];\r
+\r
+                       GetDateStrEx64(tmp, sizeof(tmp), SystemToLocal64(e->Expires), NULL);\r
+\r
+                       UniToStru(tmp2, e->Key);\r
+\r
+                       CtInsert(ct, _UU("CMD_CAList_COLUMN_ID"), tmp2);\r
+                       CtInsert(ct, _UU("CM_CERT_COLUMN_1"), e->SubjectName);\r
+                       CtInsert(ct, _UU("CM_CERT_COLUMN_2"), e->IssuerName);\r
+                       CtInsert(ct, _UU("CM_CERT_COLUMN_3"), tmp);\r
+\r
+                       if (i != (t.NumCa - 1))\r
+                       {\r
+                               CtInsert(ct, L"---", L"---");\r
+                       }\r
+               }\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeRpcHubEnumCa(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 信頼する証明機関の証明書の追加\r
+UINT PsCAAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_HUB_ADD_CA t;\r
+       X *x;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[path]", CmdPrompt, _UU("CMD_CAAdd_PROMPT_PATH"), CmdEvalIsFile, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       x = FileToX(GetParamStr(o, "[path]"));\r
+\r
+       if (x == NULL)\r
+       {\r
+               FreeParamValueList(o);\r
+               c->Write(c, _UU("CMD_MSG_LOAD_CERT_FAILED"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.Cert = x;\r
+\r
+       // RPC 呼び出し\r
+       ret = ScAddCa(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcHubAddCa(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 信頼する証明機関の証明書の削除\r
+UINT PsCADelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_HUB_DELETE_CA t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[id]", CmdPrompt, _UU("CMD_CADelete_PROMPT_ID"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.Key = GetParamInt(o, "[id]");\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDeleteCa(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 信頼する証明機関の証明書の取得\r
+UINT PsCAGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_HUB_GET_CA t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[id]", CmdPrompt, _UU("CMD_CAGet_PROMPT_ID"), CmdEvalNotEmpty, NULL},\r
+               {"SAVECERT", CmdPrompt, _UU("CMD_CAGet_PROMPT_SAVECERT"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.Key = GetParamInt(o, "[id]");\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetCa(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               if (XToFile(t.Cert, GetParamStr(o, "SAVECERT"), true))\r
+               {\r
+                       // 成功\r
+               }\r
+               else\r
+               {\r
+                       ret = ERR_INTERNAL_ERROR;\r
+                       c->Write(c, _UU("CMD_MSG_SAVE_CERT_FAILED"));\r
+               }\r
+       }\r
+\r
+       FreeRpcHubGetCa(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// カスケード接続一覧の取得\r
+UINT PsCascadeList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_LINK t;\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct = CtNew();\r
+               UINT i;\r
+\r
+               CtInsertColumn(ct, _UU("SM_LINK_COLUMN_1"), false);\r
+               CtInsertColumn(ct, _UU("SM_LINK_COLUMN_2"), false);\r
+               CtInsertColumn(ct, _UU("SM_LINK_COLUMN_3"), false);\r
+               CtInsertColumn(ct, _UU("SM_LINK_COLUMN_4"), false);\r
+               CtInsertColumn(ct, _UU("SM_LINK_COLUMN_5"), false);\r
+\r
+               for (i = 0;i < t.NumLink;i++)\r
+               {\r
+                       RPC_ENUM_LINK_ITEM *e = &t.Links[i];\r
+                       wchar_t tmp1[MAX_SIZE];\r
+                       wchar_t tmp2[MAX_SIZE];\r
+                       wchar_t tmp3[MAX_SIZE];\r
+                       wchar_t tmp4[MAX_SIZE];\r
+\r
+                       GetDateTimeStrEx64(tmp1, sizeof(tmp1), SystemToLocal64(e->ConnectedTime), NULL);\r
+                       StrToUni(tmp2, sizeof(tmp2), e->Hostname);\r
+                       StrToUni(tmp3, sizeof(tmp3), e->HubName);\r
+\r
+                       if (e->Online == false)\r
+                       {\r
+                               UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_LINK_STATUS_OFFLINE"));\r
+                       }\r
+                       else\r
+                       {\r
+                               if (e->Connected)\r
+                               {\r
+                                       UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_LINK_STATUS_ONLINE"));\r
+                               }\r
+                               else\r
+                               {\r
+                                       if (e->LastError != 0)\r
+                                       {\r
+                                               UniFormat(tmp4, sizeof(tmp4), _UU("SM_LINK_STATUS_ERROR"), e->LastError, _E(e->LastError));\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_LINK_CONNECTING"));\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       CtInsert(ct, e->AccountName, tmp4, tmp1, tmp2, tmp3);\r
+               }\r
+\r
+               CtFreeEx(ct, c, true);\r
+       }\r
+\r
+       FreeRpcEnumLink(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 新しいカスケード接続の作成\r
+UINT PsCascadeCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       char *host = NULL;\r
+       UINT port = 443;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"SERVER", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Server"), CmdEvalHostAndPort, NULL},\r
+               {"HUB", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Hub"), CmdEvalSafe, NULL},\r
+               {"USERNAME", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Username"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 443);\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       t.Online = false;\r
+\r
+       Copy(&t.Policy, GetDefaultPolicy(), sizeof(POLICY));\r
+\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+       t.ClientOption->Port = port;\r
+       StrCpy(t.ClientOption->Hostname, sizeof(t.ClientOption->Hostname), host);\r
+       StrCpy(t.ClientOption->HubName, sizeof(t.ClientOption->HubName), GetParamStr(o, "HUB"));\r
+       t.ClientOption->NumRetry = INFINITE;\r
+       t.ClientOption->RetryInterval = 15;\r
+       t.ClientOption->MaxConnection = 8;\r
+       t.ClientOption->UseEncrypt = true;\r
+       t.ClientOption->AdditionalConnectionInterval = 1;\r
+       t.ClientOption->RequireBridgeRoutingMode = true;\r
+\r
+       t.ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));\r
+       t.ClientAuth->AuthType = CLIENT_AUTHTYPE_ANONYMOUS;\r
+       StrCpy(t.ClientAuth->Username, sizeof(t.ClientAuth->Username), GetParamStr(o, "USERNAME"));\r
+\r
+       Free(host);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScCreateLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcCreateLink(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続の接続先とユーザー名の設定\r
+UINT PsCascadeSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       char *host = NULL;\r
+       UINT port = 443;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"SERVER", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Server"), CmdEvalHostAndPort, NULL},\r
+               {"HUB", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Hub"), CmdEvalSafe, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 443);\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               Free(host);\r
+               return ret;\r
+       }\r
+\r
+       t.ClientOption->Port = port;\r
+       StrCpy(t.ClientOption->Hostname, sizeof(t.ClientOption->Hostname), host);\r
+       StrCpy(t.ClientOption->HubName, sizeof(t.ClientOption->HubName), GetParamStr(o, "HUB"));\r
+\r
+       Free(host);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScSetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcCreateLink(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// プロキシの種類文字列の取得\r
+wchar_t *GetProxyTypeStr(UINT i)\r
+{\r
+       switch (i)\r
+       {\r
+       case PROXY_DIRECT:\r
+\r
+               return _UU("PROTO_DIRECT_TCP");\r
+\r
+       case PROXY_HTTP:\r
+               return _UU("PROTO_HTTP_PROXY");\r
+\r
+       case PROXY_SOCKS:\r
+               return _UU("PROTO_SOCKS_PROXY");\r
+\r
+       default:\r
+               return _UU("PROTO_UNKNOWN");\r
+       }\r
+}\r
+\r
+// クライアントのユーザー認証の種類文字列の取得\r
+wchar_t *GetClientAuthTypeStr(UINT i)\r
+{\r
+       char tmp[MAX_SIZE];\r
+\r
+       Format(tmp, sizeof(tmp), "PW_TYPE_%u", i);\r
+\r
+       return _UU(tmp);\r
+}\r
+\r
+// カスケード接続の設定の取得\r
+UINT PsCascadeGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName),\r
+               GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // 接続設定の内容を表示\r
+               wchar_t tmp[MAX_SIZE];\r
+\r
+               CT *ct = CtNewStandard();\r
+\r
+               // 接続設定名\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_NAME"), t.ClientOption->AccountName);\r
+\r
+               // 接続先 VPN Server のホスト名\r
+               StrToUni(tmp, sizeof(tmp), t.ClientOption->Hostname);\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_HOSTNAME"), tmp);\r
+\r
+               // 接続先 VPN Server のポート番号\r
+               UniToStru(tmp, t.ClientOption->Port);\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PORT"), tmp);\r
+\r
+               // 接続先 VPN Server の仮想 HUB 名\r
+               StrToUni(tmp, sizeof(tmp), t.ClientOption->HubName);\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_HUBNAME"), tmp);\r
+\r
+               // 経由するプロキシ サーバーの種類\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_TYPE"), GetProxyTypeStr(t.ClientOption->ProxyType));\r
+\r
+               if (t.ClientOption->ProxyType != PROXY_DIRECT)\r
+               {\r
+                       // プロキシ サーバーのホスト名\r
+                       StrToUni(tmp, sizeof(tmp), t.ClientOption->ProxyName);\r
+                       CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_HOSTNAME"), tmp);\r
+\r
+                       // プロキシ サーバーのポート番号\r
+                       UniToStru(tmp, t.ClientOption->ProxyPort);\r
+                       CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_PORT"), tmp);\r
+\r
+                       // プロキシ サーバーのユーザー名\r
+                       StrToUni(tmp, sizeof(tmp), t.ClientOption->ProxyUsername);\r
+                       CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_PROXY_USERNAME"), tmp);\r
+               }\r
+\r
+               // サーバー証明書の検証\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_SERVER_CERT_USE"),\r
+                       t.CheckServerCert ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               // 登録されている固有証明書\r
+               if (t.ServerCert != NULL)\r
+               {\r
+                       GetAllNameFromX(tmp, sizeof(tmp), t.ServerCert);\r
+                       CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_SERVER_CERT_NAME"), tmp);\r
+               }\r
+\r
+               // 接続に使用するデバイス名\r
+               StrToUni(tmp, sizeof(tmp), t.ClientOption->DeviceName);\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_DEVICE_NAME"), tmp);\r
+\r
+               // 認証の種類\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_AUTH_TYPE"), GetClientAuthTypeStr(t.ClientAuth->AuthType));\r
+\r
+               // ユーザー名\r
+               StrToUni(tmp, sizeof(tmp), t.ClientAuth->Username);\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_AUTH_USERNAME"), tmp);\r
+\r
+               if (t.ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)\r
+               {\r
+                       if (t.ClientAuth->ClientX != NULL)\r
+                       {\r
+                               // クライアント証明書名\r
+                               GetAllNameFromX(tmp, sizeof(tmp), t.ClientAuth->ClientX);\r
+                               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_AUTH_CERT_NAME"), tmp);\r
+                       }\r
+               }\r
+\r
+               // VPN 通信に使用する TCP コネクション数\r
+               UniToStru(tmp, t.ClientOption->MaxConnection);\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_NUMTCP"), tmp);\r
+\r
+               // 各 TCP コネクションの確立間隔\r
+               UniToStru(tmp, t.ClientOption->AdditionalConnectionInterval);\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_TCP_INTERVAL"), tmp);\r
+\r
+               // 各 TCP コネクションの寿命\r
+               if (t.ClientOption->ConnectionDisconnectSpan != 0)\r
+               {\r
+                       UniToStru(tmp, t.ClientOption->ConnectionDisconnectSpan);\r
+               }\r
+               else\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("CMD_MSG_INFINITE"));\r
+               }\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_TCP_TTL"), tmp);\r
+\r
+               // 半二重モードの使用\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_TCP_HALF"),\r
+                       t.ClientOption->HalfConnection ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               // SSL による暗号化\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_ENCRYPT"),\r
+                       t.ClientOption->UseEncrypt ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               // データ圧縮\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_COMPRESS"),\r
+                       t.ClientOption->UseCompress ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               // ブリッジ / ルータモードで接続\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_BRIDGE_ROUTER"),\r
+                       t.ClientOption->RequireBridgeRoutingMode ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               // モニタリングモードで接続\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_MONITOR"),\r
+                       t.ClientOption->RequireMonitorMode ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               // ルーティング テーブルを書き換えない\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_NO_TRACKING"),\r
+                       t.ClientOption->NoRoutingTracking ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               // QoS制御を無効化する\r
+               CtInsert(ct, _UU("CMD_ACCOUNT_COLUMN_QOS_DISABLE"),\r
+                       t.ClientOption->DisableQoS ? _UU("CMD_MSG_ENABLE") : _UU("CMD_MSG_DISABLE"));\r
+\r
+               CtFree(ct, c);\r
+\r
+               // セキュリティ ポリシー\r
+               c->Write(c, L"");\r
+               c->Write(c, _UU("CMD_CascadeGet_Policy"));\r
+               PrintPolicy(c, &t.Policy, true);\r
+       }\r
+\r
+       FreeRpcCreateLink(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続の削除\r
+UINT PsCascadeDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDeleteLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続の接続に使用するユーザー名の設定\r
+UINT PsCascadeUsernameSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"USERNAME", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Username"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // カスケード接続の設定の変更\r
+               StrCpy(t.ClientAuth->Username, sizeof(t.ClientAuth->Username),\r
+                       GetParamStr(o, "USERNAME"));\r
+\r
+               if (t.ClientAuth->AuthType == CLIENT_AUTHTYPE_PASSWORD)\r
+               {\r
+                       c->Write(c, _UU("CMD_CascadeUsername_Notice"));\r
+               }\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+//カスケード接続のユーザー認証の種類を匿名認証に設定\r
+UINT PsCascadeAnonymousSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // カスケード接続の設定の変更\r
+               t.ClientAuth->AuthType = CLIENT_AUTHTYPE_ANONYMOUS;\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続のユーザー認証の種類をパスワード認証に設定\r
+UINT PsCascadePasswordSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"PASSWORD", CmdPromptChoosePassword, NULL, NULL, NULL},\r
+               {"TYPE", CmdPrompt, _UU("CMD_CascadePasswordSet_Prompt_Type"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // カスケード接続の設定の変更\r
+               char *typestr = GetParamStr(o, "TYPE");\r
+\r
+               if (StartWith("standard", typestr))\r
+               {\r
+                       t.ClientAuth->AuthType = CLIENT_AUTHTYPE_PASSWORD;\r
+                       HashPassword(t.ClientAuth->HashedPassword, t.ClientAuth->Username,\r
+                               GetParamStr(o, "PASSWORD"));\r
+               }\r
+               else if (StartWith("radius", typestr) || StartWith("ntdomain", typestr))\r
+               {\r
+                       t.ClientAuth->AuthType = CLIENT_AUTHTYPE_PLAIN_PASSWORD;\r
+\r
+                       StrCpy(t.ClientAuth->PlainPassword, sizeof(t.ClientAuth->PlainPassword),\r
+                               GetParamStr(o, "PASSWORD"));\r
+               }\r
+               else\r
+               {\r
+                       // エラー発生\r
+                       c->Write(c, _UU("CMD_CascadePasswordSet_Type_Invalid"));\r
+                       FreeRpcCreateLink(&t);\r
+                       ret = ERR_INVALID_PARAMETER;\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ERR_INTERNAL_ERROR;\r
+               }\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続のユーザー認証の種類をクライアント証明書認証に設定\r
+UINT PsCascadeCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       X *x;\r
+       K *k;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"LOADCERT", CmdPrompt, _UU("CMD_LOADCERTPATH"), CmdEvalIsFile, NULL},\r
+               {"LOADKEY", CmdPrompt, _UU("CMD_LOADKEYPATH"), CmdEvalIsFile, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (CmdLoadCertAndKey(c, &x, &k, GetParamStr(o, "LOADCERT"), GetParamStr(o, "LOADKEY")) == false)\r
+       {\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               FreeX(x);\r
+               FreeK(k);\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // 認証データ変更\r
+               t.ClientAuth->AuthType = CLIENT_AUTHTYPE_CERT;\r
+               if (t.ClientAuth->ClientX != NULL)\r
+               {\r
+                       FreeX(t.ClientAuth->ClientX);\r
+               }\r
+               if (t.ClientAuth->ClientK != NULL)\r
+               {\r
+                       FreeK(t.ClientAuth->ClientK);\r
+               }\r
+\r
+               t.ClientAuth->ClientX = x;\r
+               t.ClientAuth->ClientK = k;\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続に用いるクライアント証明書の取得\r
+UINT PsCascadeCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"SAVECERT", CmdPrompt, _UU("CMD_SAVECERTPATH"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               if (t.ClientAuth->AuthType != CLIENT_AUTHTYPE_CERT)\r
+               {\r
+                       c->Write(c, _UU("CMD_CascadeCertSet_Not_Auth_Cert"));\r
+                       ret = ERR_INTERNAL_ERROR;\r
+               }\r
+               else if (t.ClientAuth->ClientX == NULL)\r
+               {\r
+                       c->Write(c, _UU("CMD_CascadeCertSet_Cert_Not_Exists"));\r
+                       ret = ERR_INTERNAL_ERROR;\r
+               }\r
+               else\r
+               {\r
+                       XToFile(t.ClientAuth->ClientX, GetParamStr(o, "SAVECERT"), true);\r
+               }\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// カスケード接続の通信時の暗号化の有効化\r
+UINT PsCascadeEncryptEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // データ変更\r
+               t.ClientOption->UseEncrypt = true;\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続の通信時の暗号化の無効化\r
+UINT PsCascadeEncryptDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // データ変更\r
+               t.ClientOption->UseEncrypt = false;\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続の通信時のデータ圧縮の有効化\r
+UINT PsCascadeCompressEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // データ変更\r
+               t.ClientOption->UseCompress = true;\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続の通信時のデータ圧縮の無効化\r
+UINT PsCascadeCompressDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // データ変更\r
+               t.ClientOption->UseCompress = false;\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続の接続方法を直接 TCP/IP 接続に設定\r
+UINT PsCascadeProxyNone(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // データ変更\r
+               t.ClientOption->ProxyType = PROXY_DIRECT;\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続の接続方法を HTTP プロキシサーバー経由接続に設定\r
+UINT PsCascadeProxyHttp(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"SERVER", CmdPrompt, _UU("CMD_CascadeProxyHttp_Prompt_Server"), CmdEvalHostAndPort, NULL},\r
+               {"USERNAME", NULL, NULL, NULL, NULL},\r
+               {"PASSWORD", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               char *host;\r
+               UINT port;\r
+\r
+               // データ変更\r
+               if (ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 8080))\r
+               {\r
+                       t.ClientOption->ProxyType = PROXY_HTTP;\r
+                       StrCpy(t.ClientOption->ProxyName, sizeof(t.ClientOption->ProxyName), host);\r
+                       t.ClientOption->ProxyPort = port;\r
+                       StrCpy(t.ClientOption->ProxyUsername, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "USERNAME"));\r
+                       StrCpy(t.ClientOption->ProxyPassword, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "PASSWORD"));\r
+                       Free(host);\r
+               }\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続の接続方法を SOCKS プロキシサーバー経由接続に設定\r
+UINT PsCascadeProxySocks(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"SERVER", CmdPrompt, _UU("CMD_CascadeProxyHttp_Prompt_Server"), CmdEvalHostAndPort, NULL},\r
+               {"USERNAME", NULL, NULL, NULL, NULL},\r
+               {"PASSWORD", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               char *host;\r
+               UINT port;\r
+\r
+               // データ変更\r
+               if (ParseHostPort(GetParamStr(o, "SERVER"), &host, &port, 8080))\r
+               {\r
+                       t.ClientOption->ProxyType = PROXY_SOCKS;\r
+                       StrCpy(t.ClientOption->ProxyName, sizeof(t.ClientOption->ProxyName), host);\r
+                       t.ClientOption->ProxyPort = port;\r
+                       StrCpy(t.ClientOption->ProxyUsername, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "USERNAME"));\r
+                       StrCpy(t.ClientOption->ProxyPassword, sizeof(t.ClientOption->ProxyName), GetParamStr(o, "PASSWORD"));\r
+                       Free(host);\r
+               }\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続のサーバー証明書の検証オプションの有効化\r
+UINT PsCascadeServerCertEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // データ変更\r
+               t.CheckServerCert = true;\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続のサーバー証明書の検証オプションの無効化\r
+UINT PsCascadeServerCertDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // データ変更\r
+               t.CheckServerCert = false;\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続のサーバー固有証明書の設定\r
+UINT PsCascadeServerCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       X *x;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"LOADCERT", CmdPrompt, _UU("CMD_LOADCERTPATH"), CmdEvalIsFile, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       x = FileToX(GetParamStr(o, "LOADCERT"));\r
+       if (x == NULL)\r
+       {\r
+               FreeParamValueList(o);\r
+               c->Write(c, _UU("CMD_LOADCERT_FAILED"));\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               FreeX(x);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // データ変更\r
+               if (t.ServerCert != NULL)\r
+               {\r
+                       FreeX(t.ServerCert);\r
+               }\r
+               t.ServerCert = x;\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続のサーバー固有証明書の削除\r
+UINT PsCascadeServerCertDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // データ変更\r
+               if (t.ServerCert != NULL)\r
+               {\r
+                       FreeX(t.ServerCert);\r
+               }\r
+               t.ServerCert = NULL;\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続のサーバー固有証明書の取得\r
+UINT PsCascadeServerCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"SAVECERT", CmdPrompt, _UU("CMD_SAVECERTPATH"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // 証明書保存\r
+               if (t.ServerCert == NULL)\r
+               {\r
+                       c->Write(c, _UU("CMD_CERT_NOT_EXISTS"));\r
+                       ret = ERR_INTERNAL_ERROR;\r
+               }\r
+               else\r
+               {\r
+                       if (XToFile(t.ServerCert, GetParamStr(o, "SAVECERT"), true) == false)\r
+                       {\r
+                               c->Write(c, _UU("CMD_SAVECERT_FAILED"));\r
+                               ret = ERR_INTERNAL_ERROR;\r
+                       }\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// カスケード接続の高度な通信設定の設定\r
+UINT PsCascadeDetailSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       CMD_EVAL_MIN_MAX mm_maxtcp =\r
+       {\r
+               "CMD_CascadeDetailSet_Eval_MaxTcp", 1, 32\r
+       };\r
+       CMD_EVAL_MIN_MAX mm_interval =\r
+       {\r
+               "CMD_CascadeDetailSet_Eval_Interval", 1, 4294967295UL\r
+       };\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"MAXTCP", CmdPrompt, _UU("CMD_CascadeDetailSet_Prompt_MaxTcp"), CmdEvalMinMax, &mm_maxtcp},\r
+               {"INTERVAL", CmdPrompt, _UU("CMD_CascadeDetailSet_Prompt_Interval"), CmdEvalMinMax, &mm_interval},\r
+               {"TTL", CmdPrompt, _UU("CMD_CascadeDetailSet_Prompt_TTL"), NULL, NULL},\r
+               {"HALF", CmdPrompt, _UU("CMD_CascadeDetailSet_Prompt_HALF"), NULL, NULL},\r
+               {"NOQOS", CmdPrompt, _UU("CMD_AccountDetailSet_Prompt_NOQOS"), NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // データ変更\r
+               t.ClientOption->MaxConnection = GetParamInt(o, "MAXTCP");\r
+               t.ClientOption->AdditionalConnectionInterval = GetParamInt(o, "INTERVAL");\r
+               t.ClientOption->ConnectionDisconnectSpan = GetParamInt(o, "TTL");\r
+               t.ClientOption->HalfConnection = GetParamYes(o, "HALF");\r
+               t.ClientOption->DisableQoS = GetParamYes(o, "NOQOS");\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// セキュリティ ポリシーを表示\r
+void PrintPolicy(CONSOLE *c, POLICY *pol, bool cascade_mode)\r
+{\r
+       UINT i;\r
+       CT *ct;\r
+       PACK *p;\r
+       // 引数チェック\r
+       if (c == NULL || pol == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       ct = CtNew();\r
+       CtInsertColumn(ct, _UU("CMD_PolicyList_Column_1"), false);\r
+       CtInsertColumn(ct, _UU("CMD_PolicyList_Column_2"), false);\r
+       CtInsertColumn(ct, _UU("CMD_PolicyList_Column_3"), false);\r
+\r
+       p = NewPack();\r
+       OutRpcPolicy(p, pol);\r
+\r
+       // すべてのポリシー一覧を表示する\r
+       for (i = 0; i < PolicyNum();i++)\r
+       {\r
+               char name[64];\r
+               wchar_t *tmp;\r
+\r
+               if (cascade_mode == false || PolicyIsSupportedForCascade(i))\r
+               {\r
+                       wchar_t value_str[256];\r
+                       UINT value;\r
+                       char tmp2[256];\r
+\r
+                       Format(tmp2, sizeof(tmp2), "policy:%s", PolicyIdToStr(i));\r
+                       value = PackGetInt(p, tmp2);\r
+\r
+                       tmp = CopyStrToUni(PolicyIdToStr(i));\r
+\r
+                       FormatPolicyValue(value_str, sizeof(value_str),\r
+                               i, value);\r
+\r
+                       Format(name, sizeof(name), "POL_%u", i);\r
+                       CtInsert(ct, tmp, _UU(name), value_str);\r
+\r
+                       Free(tmp);\r
+               }\r
+       }\r
+\r
+       FreePack(p);\r
+\r
+       CtFree(ct, c);\r
+}\r
+\r
+// セキュリティ ポリシー リストを表示\r
+void PrintPolicyList(CONSOLE *c, char *name)\r
+{\r
+       UINT id;\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return;\r
+       }\r
+       if (IsEmptyStr(name))\r
+       {\r
+               name = NULL;\r
+       }\r
+\r
+       if (name != NULL)\r
+       {\r
+               id = PolicyStrToId(name);\r
+               if (id == INFINITE)\r
+               {\r
+                       // 不正な ID\r
+                       c->Write(c, _UU("CMD_PolicyList_Invalid_Name"));\r
+               }\r
+               else\r
+               {\r
+                       wchar_t tmp[MAX_SIZE];\r
+                       wchar_t tmp2[MAX_SIZE];\r
+                       char name1[64], name2[64];\r
+                       wchar_t *title, *descript;\r
+                       wchar_t policy_name[MAX_SIZE];\r
+\r
+                       Format(name1, sizeof(name1), "POL_%u", id);\r
+                       Format(name2, sizeof(name2), "POL_EX_%u", id);\r
+\r
+                       title = _UU(name1);\r
+                       descript = _UU(name2);\r
+\r
+                       StrToUni(policy_name, sizeof(policy_name), PolicyIdToStr(id));\r
+\r
+                       // ポリシー名\r
+                       c->Write(c, _UU("CMD_PolicyList_Help_1"));\r
+                       UniFormat(tmp2, sizeof(tmp2), L" %s", policy_name);\r
+                       c->Write(c, tmp2);\r
+                       c->Write(c, L"");\r
+\r
+                       // ポリシーの簡易説明\r
+                       c->Write(c, _UU("CMD_PolicyList_Help_2"));\r
+                       UniFormat(tmp2, sizeof(tmp2), L" %s", title);\r
+                       c->Write(c, tmp2);\r
+                       c->Write(c, L"");\r
+\r
+                       // 設定できる値の範囲\r
+                       GetPolicyValueRangeStr(tmp, sizeof(tmp), id);\r
+                       c->Write(c, _UU("CMD_PolicyList_Help_3"));\r
+                       UniFormat(tmp2, sizeof(tmp2), L" %s", tmp);\r
+                       c->Write(c, tmp2);\r
+                       c->Write(c, L"");\r
+\r
+                       // デフォルト値\r
+                       FormatPolicyValue(tmp, sizeof(tmp), id, GetPolicyItem(id)->DefaultValue);\r
+                       c->Write(c, _UU("CMD_PolicyList_Help_4"));\r
+                       UniFormat(tmp2, sizeof(tmp2), L" %s", tmp);\r
+                       c->Write(c, tmp2);\r
+                       c->Write(c, L"");\r
+\r
+                       // ポリシーの詳細説明\r
+                       c->Write(c, _UU("CMD_PolicyList_Help_5"));\r
+                       c->Write(c, descript);\r
+                       c->Write(c, L"");\r
+               }\r
+       }\r
+       else\r
+       {\r
+               UINT i;\r
+               CT *ct = CtNew();\r
+               CtInsertColumn(ct, _UU("CMD_PolicyList_Column_1"), false);\r
+               CtInsertColumn(ct, _UU("CMD_PolicyList_Column_2"), false);\r
+\r
+               // すべてのポリシー一覧を表示する\r
+               for (i = 0; i < PolicyNum();i++)\r
+               {\r
+                       char name[64];\r
+                       wchar_t *tmp;\r
+\r
+                       tmp = CopyStrToUni(PolicyIdToStr(i));\r
+\r
+                       Format(name, sizeof(name), "POL_%u", i);\r
+                       CtInsert(ct, tmp, _UU(name));\r
+\r
+                       Free(tmp);\r
+               }\r
+\r
+               CtFree(ct, c);\r
+       }\r
+}\r
+\r
+// ポリシーの内容の編集\r
+bool EditPolicy(CONSOLE *c, POLICY *pol, char *name, char *value, bool cascade_mode)\r
+{\r
+       PACK *p;\r
+       ELEMENT *e;\r
+       POLICY_ITEM *item;\r
+       UINT id;\r
+       wchar_t tmp[MAX_SIZE];\r
+       wchar_t tmp2[MAX_SIZE];\r
+       char pack_name[128];\r
+       // 引数チェック\r
+       if (c == NULL || pol == NULL || name == NULL || value == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       p = NewPack();\r
+\r
+       OutRpcPolicy(p, pol);\r
+\r
+       Format(pack_name, sizeof(pack_name), "policy:%s", PolicyIdToStr(PolicyStrToId(name)));\r
+\r
+       if ((e = GetElement(p, pack_name, VALUE_INT)) == NULL || (id = PolicyStrToId(name)) == INFINITE)\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), _UU("CMD_CascadePolicySet_Invalid_Name"), name);\r
+               c->Write(c, tmp);\r
+               FreePack(p);\r
+               return false;\r
+       }\r
+\r
+       if (cascade_mode && (PolicyIsSupportedForCascade(id) == false))\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), _UU("CMD_CascadePolicySet_Invalid_Name_For_Cadcade"), name);\r
+               c->Write(c, tmp);\r
+               FreePack(p);\r
+               return false;\r
+       }\r
+\r
+       item = GetPolicyItem(id);\r
+\r
+       if (item->TypeInt == false)\r
+       {\r
+               // bool 型\r
+               e->values[0]->IntValue = (\r
+                       StartWith(value, "y") || StartWith(value, "t") ||\r
+                       ToInt(value) != 0) ? 1 : 0;\r
+       }\r
+       else\r
+       {\r
+               UINT n = ToInt(value);\r
+               bool b = true;\r
+\r
+               // int 型\r
+               GetPolicyValueRangeStr(tmp, sizeof(tmp), id);\r
+\r
+               if (item->AllowZero == false)\r
+               {\r
+                       if (n == 0)\r
+                       {\r
+                               b = false;\r
+                       }\r
+               }\r
+\r
+               if (n != 0 && (n < item->MinValue || n > item->MaxValue))\r
+               {\r
+                       b = false;\r
+               }\r
+\r
+               if (b == false)\r
+               {\r
+                       UniFormat(tmp2, sizeof(tmp2), _UU("CMD_CascadePolicySet_Invalid_Range"), PolicyIdToStr(id), tmp);\r
+                       c->Write(c, tmp2);\r
+                       FreePack(p);\r
+                       return false;\r
+               }\r
+\r
+               e->values[0]->IntValue = n;\r
+       }\r
+\r
+       Zero(pol, sizeof(POLICY));\r
+\r
+       InRpcPolicy(pol, p);\r
+\r
+       FreePack(p);\r
+\r
+       return true;\r
+}\r
+\r
+// セキュリティ ポリシーの種類と設定可能値の一覧を表示\r
+UINT PsPolicyList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", NULL, NULL, NULL, NULL}\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       PrintPolicyList(c, GetParamStr(o, "[name]"));\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return ERR_NO_ERROR;\r
+}\r
+\r
+// カスケード接続セッションのセキュリティ ポリシーの設定\r
+UINT PsCascadePolicySet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CREATE_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+               {"NAME", CmdPrompt, _UU("CMD_CascadePolicySet_PROMPT_POLNAME"), CmdEvalNotEmpty, NULL},\r
+               {"VALUE", CmdPrompt, _UU("CMD_CascadePolicySet_PROMPT_POLVALUE"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               if (EditPolicy(c, &t.Policy, GetParamStr(o, "NAME"), GetParamStr(o, "VALUE"), true) == false)\r
+               {\r
+                       // エラー発生\r
+                       FreeRpcCreateLink(&t);\r
+                       FreeParamValueList(o);\r
+                       return ERR_INTERNAL_ERROR;\r
+               }\r
+\r
+               ret = ScSetLink(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// セッションのステータス情報の表示\r
+void CmdPrintStatusToListView(CT *ct, RPC_CLIENT_GET_CONNECTION_STATUS *s)\r
+{\r
+       CmdPrintStatusToListViewEx(ct, s, false);\r
+}\r
+void CmdPrintStatusToListViewEx(CT *ct, RPC_CLIENT_GET_CONNECTION_STATUS *s, bool server_mode)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       char str[MAX_SIZE];\r
+       char vv[128];\r
+       // 引数チェック\r
+       if (s == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (server_mode == false)\r
+       {\r
+               CtInsert(ct, _UU("CM_ST_ACCOUNT_NAME"), s->AccountName);\r
+\r
+               if (s->Connected == false)\r
+               {\r
+                       wchar_t *st = _UU("CM_ST_CONNECTED_FALSE");\r
+                       switch (s->SessionStatus)\r
+                       {\r
+                       case CLIENT_STATUS_CONNECTING:\r
+                               st = _UU("CM_ST_CONNECTING");\r
+                               break;\r
+                       case CLIENT_STATUS_NEGOTIATION:\r
+                               st = _UU("CM_ST_NEGOTIATION");\r
+                               break;\r
+                       case CLIENT_STATUS_AUTH:\r
+                               st = _UU("CM_ST_AUTH");\r
+                               break;\r
+                       case CLIENT_STATUS_ESTABLISHED:\r
+                               st = _UU("CM_ST_ESTABLISHED");\r
+                               break;\r
+                       case CLIENT_STATUS_RETRY:\r
+                               st = _UU("CM_ST_RETRY");\r
+                               break;\r
+                       case CLIENT_STATUS_IDLE:\r
+                               st = _UU("CM_ST_IDLE");\r
+                               break;\r
+                       }\r
+                       CtInsert(ct, _UU("CM_ST_CONNECTED"), st);\r
+               }\r
+               else\r
+               {\r
+                       CtInsert(ct, _UU("CM_ST_CONNECTED"), _UU("CM_ST_CONNECTED_TRUE"));\r
+               }\r
+       }\r
+\r
+       if (s->Connected)\r
+       {\r
+               if (s->VLanId == 0)\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("CM_ST_NO_VLAN"));\r
+               }\r
+               else\r
+               {\r
+                       UniToStru(tmp, s->VLanId);\r
+               }\r
+\r
+               CtInsert(ct, _UU("CM_ST_VLAN_ID"), tmp);\r
+\r
+               if (server_mode == false)\r
+               {\r
+                       StrToUni(tmp, sizeof(tmp), s->ServerName);\r
+                       CtInsert(ct, _UU("CM_ST_SERVER_NAME"), tmp);\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_ST_PORT_TCP"), s->ServerPort);\r
+                       CtInsert(ct, _UU("CM_ST_SERVER_PORT"), tmp);\r
+               }\r
+\r
+               StrToUni(tmp, sizeof(tmp), s->ServerProductName);\r
+               CtInsert(ct, _UU("CM_ST_SERVER_P_NAME"), tmp);\r
+\r
+               UniFormat(tmp, sizeof(tmp), L"%u.%02u", s->ServerProductVer / 100, s->ServerProductVer % 100);\r
+               CtInsert(ct, _UU("CM_ST_SERVER_P_VER"), tmp);\r
+               UniFormat(tmp, sizeof(tmp), L"Build %u", s->ServerProductBuild);\r
+               CtInsert(ct, _UU("CM_ST_SERVER_P_BUILD"), tmp);\r
+       }\r
+\r
+       GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(s->StartTime), NULL);\r
+       CtInsert(ct, _UU("CM_ST_START_TIME"), tmp);\r
+       GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(s->FirstConnectionEstablisiedTime), NULL);\r
+       CtInsert(ct, _UU("CM_ST_FIRST_ESTAB_TIME"), s->FirstConnectionEstablisiedTime == 0 ? _UU("CM_ST_NONE") : tmp);\r
+\r
+       if (s->Connected)\r
+       {\r
+               GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(s->CurrentConnectionEstablishTime), NULL);\r
+               CtInsert(ct, _UU("CM_ST_CURR_ESTAB_TIME"), tmp);\r
+       }\r
+\r
+       if (server_mode == false)\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_STR"), s->NumConnectionsEatablished);\r
+               CtInsert(ct, _UU("CM_ST_NUM_ESTABLISHED"), tmp);\r
+       }\r
+\r
+       if (s->Connected)\r
+       {\r
+               CtInsert(ct, _UU("CM_ST_HALF_CONNECTION"), s->HalfConnection ? _UU("CM_ST_HALF_TRUE") : _UU("CM_ST_HALF_FALSE"));\r
+\r
+               CtInsert(ct, _UU("CM_ST_QOS"), s->QoS ? _UU("CM_ST_QOS_TRUE") : _UU("CM_ST_QOS_FALSE"));\r
+\r
+               UniFormat(tmp, sizeof(tmp), L"%u", s->NumTcpConnections);\r
+               CtInsert(ct, _UU("CM_ST_NUM_TCP"), tmp);\r
+\r
+               if (s->HalfConnection)\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), L"%u", s->NumTcpConnectionsUpload);\r
+                       CtInsert(ct, _UU("CM_ST_NUM_TCP_UPLOAD"), tmp);\r
+                       UniFormat(tmp, sizeof(tmp), L"%u", s->NumTcpConnectionsDownload);\r
+                       CtInsert(ct, _UU("CM_ST_NUM_TCP_DOWNLOAD"), tmp);\r
+               }\r
+\r
+               UniFormat(tmp, sizeof(tmp), L"%u", s->MaxTcpConnections);\r
+               CtInsert(ct, _UU("CM_ST_MAX_TCP"), tmp);\r
+\r
+               if (s->UseEncrypt == false)\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("CM_ST_USE_ENCRYPT_FALSE"));\r
+               }\r
+               else\r
+               {\r
+                       if (StrLen(s->CipherName) != 0)\r
+                       {\r
+                               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_USE_ENCRYPT_TRUE"), s->CipherName);\r
+                       }\r
+                       else\r
+                       {\r
+                               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_USE_ENCRYPT_TRUE2"));\r
+                       }\r
+               }\r
+               CtInsert(ct, _UU("CM_ST_USE_ENCRYPT"), tmp);\r
+\r
+               if (s->UseCompress)\r
+               {\r
+                       UINT percent = 0;\r
+                       if ((s->TotalRecvSize + s->TotalSendSize) > 0)\r
+                       {\r
+                               percent = (UINT)((UINT64)100 - (UINT64)(s->TotalRecvSizeReal + s->TotalSendSizeReal) * (UINT64)100 /\r
+                                       (s->TotalRecvSize + s->TotalSendSize));\r
+                               percent = MAKESURE(percent, 0, 100);\r
+                       }\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CM_ST_COMPRESS_TRUE"), percent);\r
+               }\r
+               else\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("CM_ST_COMPRESS_FALSE"));\r
+               }\r
+               CtInsert(ct, _UU("CM_ST_USE_COMPRESS"), tmp);\r
+\r
+               StrToUni(tmp, sizeof(tmp), s->SessionName);\r
+               CtInsert(ct, _UU("CM_ST_SESSION_NAME"), tmp);\r
+\r
+               StrToUni(tmp, sizeof(tmp), s->ConnectionName);\r
+               if (UniStrCmpi(tmp, L"INITING") != 0)\r
+               {\r
+                       CtInsert(ct, _UU("CM_ST_CONNECTION_NAME"), tmp);\r
+               }\r
+\r
+               BinToStr(str, sizeof(str), s->SessionKey, sizeof(s->SessionKey));\r
+               StrToUni(tmp, sizeof(tmp), str);\r
+               CtInsert(ct, _UU("CM_ST_SESSION_KEY"), tmp);\r
+\r
+               CtInsert(ct, _UU("CM_ST_BRIDGE_MODE"), s->IsBridgeMode ? _UU("CM_ST_YES") : _UU("CM_ST_NO"));\r
+\r
+               CtInsert(ct, _UU("CM_ST_MONITOR_MODE"), s->IsMonitorMode ? _UU("CM_ST_YES") : _UU("CM_ST_NO"));\r
+\r
+               ToStr3(vv, sizeof(vv), s->TotalSendSize);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);\r
+               CtInsert(ct, _UU("CM_ST_SEND_SIZE"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->TotalRecvSize);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);\r
+               CtInsert(ct, _UU("CM_ST_RECV_SIZE"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Send.UnicastCount);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);\r
+               CtInsert(ct, _UU("CM_ST_SEND_UCAST_NUM"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Send.UnicastBytes);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);\r
+               CtInsert(ct, _UU("CM_ST_SEND_UCAST_SIZE"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Send.BroadcastCount);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);\r
+               CtInsert(ct, _UU("CM_ST_SEND_BCAST_NUM"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Send.BroadcastBytes);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);\r
+               CtInsert(ct, _UU("CM_ST_SEND_BCAST_SIZE"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Recv.UnicastCount);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);\r
+               CtInsert(ct, _UU("CM_ST_RECV_UCAST_NUM"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Recv.UnicastBytes);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);\r
+               CtInsert(ct, _UU("CM_ST_RECV_UCAST_SIZE"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Recv.BroadcastCount);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_NUM_PACKET_STR"), vv);\r
+               CtInsert(ct, _UU("CM_ST_RECV_BCAST_NUM"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), s->Traffic.Recv.BroadcastBytes);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_ST_SIZE_BYTE_STR"), vv);\r
+               CtInsert(ct, _UU("CM_ST_RECV_BCAST_SIZE"), tmp);\r
+       }\r
+}\r
+\r
+// カスケード接続の現在の状態の取得\r
+UINT PsCascadeStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_LINK_STATUS t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLinkStatus(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // カスケード接続状態の取得\r
+               CT *ct = CtNewStandard();\r
+\r
+               CmdPrintStatusToListView(ct, &t.Status);\r
+\r
+               CtFree(ct, c);\r
+\r
+               FreeRpcLinkStatus(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続の名前の変更\r
+UINT PsCascadeRename(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_RENAME_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeRename_PROMPT_OLD"), CmdEvalNotEmpty, NULL},\r
+               {"NEW", CmdPrompt, _UU("CMD_CascadeRename_PROMPT_NEW"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       UniStrCpy(t.NewAccountName, sizeof(t.NewAccountName), GetParamUniStr(o, "NEW"));\r
+       UniStrCpy(t.OldAccountName, sizeof(t.OldAccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScRenameLink(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続のオンライン状態への設定\r
+UINT PsCascadeOnline(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScSetLinkOnline(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// カスケード接続のオフライン状態への設定\r
+UINT PsCascadeOffline(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_LINK t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_CascadeCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScSetLinkOffline(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 文字列を pass/discard に変換\r
+bool StrToPassOrDiscard(char *str)\r
+{\r
+       // 引数チェック\r
+       if (str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (ToInt(str) != 0)\r
+       {\r
+               return true;\r
+       }\r
+\r
+       if (StartWith(str, "p") || StartWith(str, "y") || StartWith(str, "t"))\r
+       {\r
+               return true;\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+// 文字列をプロトコルに変換\r
+UINT StrToProtocol(char *str)\r
+{\r
+       if (IsEmptyStr(str))\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       if (StartWith("ip", str))\r
+       {\r
+               return 0;\r
+       }\r
+       else if (StartWith("tcp", str))\r
+       {\r
+               return IP_PROTO_TCP;\r
+       }\r
+       else if (StartWith("udp", str))\r
+       {\r
+               return IP_PROTO_UDP;\r
+       }\r
+       else if (StartWith("icmpv4", str))\r
+       {\r
+               return IP_PROTO_ICMPV4;\r
+       }\r
+       else if (StartWith("icmpv6", str))\r
+       {\r
+               return IP_PROTO_ICMPV6;\r
+       }\r
+\r
+       if (ToInt(str) == 0)\r
+       {\r
+               if (StrCmpi(str, "0") == 0)\r
+               {\r
+                       return 0;\r
+               }\r
+               else\r
+               {\r
+                       return INFINITE;\r
+               }\r
+       }\r
+\r
+       if (ToInt(str) >= 256)\r
+       {\r
+               return INFINITE;\r
+       }\r
+\r
+       return ToInt(str);\r
+}\r
+\r
+// プロトコル名のチェック\r
+bool CmdEvalProtocol(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       char tmp[64];\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       UniToStr(tmp, sizeof(tmp), str);\r
+\r
+       if (StrToProtocol(tmp) == INFINITE)\r
+       {\r
+               c->Write(c, _UU("CMD_PROTOCOL_EVAL_FAILED"));\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// ポート範囲のパース\r
+bool ParsePortRange(char *str, UINT *start, UINT *end)\r
+{\r
+       UINT a = 0, b = 0;\r
+       TOKEN_LIST *t;\r
+       // 引数チェック\r
+       if (str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (IsEmptyStr(str) == false)\r
+       {\r
+\r
+               t = ParseToken(str, "\t -");\r
+\r
+               if (t->NumTokens == 1)\r
+               {\r
+                       a = b = ToInt(t->Token[0]);\r
+               }\r
+               else if (t->NumTokens == 2)\r
+               {\r
+                       a = ToInt(t->Token[0]);\r
+                       b = ToInt(t->Token[1]);\r
+               }\r
+\r
+               FreeToken(t);\r
+\r
+               if (a > b)\r
+               {\r
+                       return false;\r
+               }\r
+\r
+               if (a >= 65536 || b >= 65536)\r
+               {\r
+                       return false;\r
+               }\r
+\r
+               if (a == 0 && b != 0)\r
+               {\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       if (start != NULL)\r
+       {\r
+               *start = a;\r
+       }\r
+       if (end != NULL)\r
+       {\r
+               *end = b;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// ポート範囲のチェック\r
+bool CmdEvalPortRange(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       char tmp[64];\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       UniToStr(tmp, sizeof(tmp), str);\r
+\r
+       if (ParsePortRange(tmp, NULL, NULL) == false)\r
+       {\r
+               c->Write(c, _UU("CMD_PORT_RANGE_EVAL_FAILED"));\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// MAC アドレスとマスクのパース\r
+bool ParseMacAddressAndMask(char *src, bool *check_mac, UCHAR *mac_bin, UCHAR *mask_bin)\r
+{\r
+       TOKEN_LIST *t;\r
+       char *macstr, *maskstr;\r
+       UCHAR mac[6], mask[6];\r
+       bool ok = false;\r
+\r
+       // 引数チェック\r
+       if (src == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       //Zero(mac, sizeof(mac));\r
+       //Zero(mask, sizeof(mask));\r
+\r
+       if(check_mac != NULL && mac_bin != NULL && mask_bin != NULL)\r
+       {\r
+               ok = true;\r
+       }\r
+       if(IsEmptyStr(src) != false)\r
+       {\r
+               if(ok != false)\r
+               {\r
+                       *check_mac = false;\r
+                       Zero(mac_bin, 6);\r
+                       Zero(mask_bin, 6);\r
+               }\r
+               return true;\r
+       }\r
+\r
+       t = ParseToken(src, "/");\r
+       if(t->NumTokens != 2)\r
+       {\r
+               FreeToken(t);\r
+               return false;\r
+       }\r
+\r
+       macstr = t->Token[0];\r
+       maskstr = t->Token[1];\r
+\r
+       Trim(macstr);\r
+       Trim(maskstr);\r
+\r
+       if(StrToMac(mac, macstr) == false || StrToMac(mask, maskstr) == false)\r
+       {\r
+               FreeToken(t);\r
+               return false;\r
+       }\r
+       else\r
+       {\r
+               if(ok != false)\r
+               {\r
+                       Copy(mac_bin, mac, 6);\r
+                       Copy(mask_bin, mask, 6);\r
+                       *check_mac = true;\r
+               }\r
+       }\r
+       FreeToken(t);\r
+\r
+       return true;\r
+}\r
+\r
+// MAC アドレスとマスクのチェック\r
+bool CmdEvalMacAddressAndMask(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       char tmp[64];\r
+       // 引数チェック\r
+       if(c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       UniToStr(tmp, sizeof(tmp), str);\r
+\r
+\r
+       if(ParseMacAddressAndMask(tmp, NULL, NULL, NULL) == false)\r
+       {\r
+               c->Write(c, _UU("CMD_MAC_ADDRESS_AND_MASK_EVAL_FAILED"));\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+// TCP コネクションの状態パース\r
+bool ParseTcpState(char *src, bool *check_tcp_state, bool *established)\r
+{\r
+       bool ok = false;\r
+       // 引数チェック\r
+       if(src == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if(check_tcp_state != NULL && established != NULL)\r
+       {\r
+               ok = true;\r
+       }\r
+\r
+       if (IsEmptyStr(src) == false)\r
+       {\r
+               if (StartWith("Established", src) == 0)\r
+               {\r
+                       if(ok != false)\r
+                       {\r
+                               *check_tcp_state = true;\r
+                               *established = true;\r
+                       }\r
+               }\r
+               else if (StartWith("Unestablished", src) == 0)\r
+               {\r
+                       if(ok != false)\r
+                       {\r
+                               *check_tcp_state = true;\r
+                               *established = false;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       // 不正な文字列\r
+                       return false;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if(ok != false)\r
+               {\r
+                       *check_tcp_state = false;\r
+                       *established = false;\r
+               }\r
+       }\r
+\r
+       return true;\r
+}\r
+// TCP コネクションの状態チェック\r
+bool CmdEvalTcpState(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       char tmp[64];\r
+       // 引数チェック\r
+       if(c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       UniToStr(tmp, sizeof(tmp), str);\r
+\r
+       if(ParseTcpState(tmp, NULL, NULL) == false)\r
+       {\r
+               c->Write(c, _UU("CMD_TCP_CONNECTION_STATE_EVAL_FAILED"));\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// アクセス リストへのルールの追加 (標準、IPv4)\r
+UINT PsAccessAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ADD_ACCESS t;\r
+       ACCESS *a;\r
+       // 指定できるパラメータ リスト\r
+       CMD_EVAL_MIN_MAX minmax =\r
+       {\r
+               "CMD_AccessAdd_Eval_PRIORITY", 1, 4294967295UL,\r
+       };\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[pass|discard]", CmdPrompt, _UU("CMD_AccessAdd_Prompt_TYPE"), CmdEvalNotEmpty, NULL},\r
+               {"MEMO", CmdPrompt, _UU("CMD_AccessAdd_Prompt_MEMO"), NULL, NULL},\r
+               {"PRIORITY", CmdPrompt, _UU("CMD_AccessAdd_Prompt_PRIORITY"), CmdEvalMinMax, &minmax},\r
+               {"SRCUSERNAME", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCUSERNAME"), NULL, NULL},\r
+               {"DESTUSERNAME", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTUSERNAME"), NULL, NULL},\r
+               {"SRCMAC", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCMAC"), CmdEvalMacAddressAndMask, NULL},\r
+               {"DESTMAC", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTMAC"), CmdEvalMacAddressAndMask, NULL},\r
+               {"SRCIP", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCIP"), CmdEvalIpAndMask4, NULL},\r
+               {"DESTIP", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTIP"), CmdEvalIpAndMask4, NULL},\r
+               {"PROTOCOL", CmdPrompt, _UU("CMD_AccessAdd_Prompt_PROTOCOL"), CmdEvalProtocol, NULL},\r
+               {"SRCPORT", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCPORT"), CmdEvalPortRange, NULL},\r
+               {"DESTPORT", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTPORT"), CmdEvalPortRange, NULL},\r
+               {"TCPSTATE", CmdPrompt, _UU("CMD_AccessAdd_Prompt_TCPSTATE"), CmdEvalTcpState, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       a = &t.Access;\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       UniStrCpy(a->Note, sizeof(a->Note), GetParamUniStr(o, "MEMO"));\r
+       a->Active = true;\r
+       a->Priority = GetParamInt(o, "PRIORITY");\r
+       a->Discard = StrToPassOrDiscard(GetParamStr(o, "[pass|discard]")) ? false : true;\r
+       StrCpy(a->SrcUsername, sizeof(a->SrcUsername), GetParamStr(o, "SRCUSERNAME"));\r
+       StrCpy(a->DestUsername, sizeof(a->DestUsername), GetParamStr(o, "DESTUSERNAME"));\r
+       ParseMacAddressAndMask(GetParamStr(o, "SRCMAC"), &a->CheckSrcMac, a->SrcMacAddress, a->SrcMacMask);\r
+       ParseMacAddressAndMask(GetParamStr(o, "DESTMAC"), &a->CheckDstMac, a->DstMacAddress, a->DstMacMask);\r
+       ParseIpAndMask4(GetParamStr(o, "SRCIP"), &a->SrcIpAddress, &a->SrcSubnetMask);\r
+       ParseIpAndMask4(GetParamStr(o, "DESTIP"), &a->DestIpAddress, &a->DestSubnetMask);\r
+       a->Protocol = StrToProtocol(GetParamStr(o, "PROTOCOL"));\r
+       ParsePortRange(GetParamStr(o, "SRCPORT"), &a->SrcPortStart, &a->SrcPortEnd);\r
+       ParsePortRange(GetParamStr(o, "DESTPORT"), &a->DestPortStart, &a->DestPortEnd);\r
+       ParseTcpState(GetParamStr(o, "TCPSTATE"), &a->CheckTcpState, &a->Established);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScAddAccess(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// アクセス リストへのルールの追加 (拡張、IPv4)\r
+UINT PsAccessAddEx(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ADD_ACCESS t;\r
+       ACCESS *a;\r
+       // 指定できるパラメータ リスト\r
+       CMD_EVAL_MIN_MAX minmax =\r
+       {\r
+               "CMD_AccessAdd_Eval_PRIORITY", 1, 4294967295UL,\r
+       };\r
+       CMD_EVAL_MIN_MAX minmax_delay =\r
+       {\r
+               "CMD_AccessAddEx_Eval_DELAY", 0, HUB_ACCESSLIST_DELAY_MAX,\r
+       };\r
+       CMD_EVAL_MIN_MAX minmax_jitter =\r
+       {\r
+               "CMD_AccessAddEx_Eval_JITTER", 0, HUB_ACCESSLIST_JITTER_MAX,\r
+       };\r
+       CMD_EVAL_MIN_MAX minmax_loss =\r
+       {\r
+               "CMD_AccessAddEx_Eval_LOSS", 0, HUB_ACCESSLIST_LOSS_MAX,\r
+       };\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[pass|discard]", CmdPrompt, _UU("CMD_AccessAdd_Prompt_TYPE"), CmdEvalNotEmpty, NULL},\r
+               {"MEMO", CmdPrompt, _UU("CMD_AccessAdd_Prompt_MEMO"), NULL, NULL},\r
+               {"PRIORITY", CmdPrompt, _UU("CMD_AccessAdd_Prompt_PRIORITY"), CmdEvalMinMax, &minmax},\r
+               {"SRCUSERNAME", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCUSERNAME"), NULL, NULL},\r
+               {"DESTUSERNAME", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTUSERNAME"), NULL, NULL},\r
+               {"SRCMAC", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCMAC"), CmdEvalMacAddressAndMask, NULL},\r
+               {"DESTMAC", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTMAC"), CmdEvalMacAddressAndMask, NULL},\r
+               {"SRCIP", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCIP"), CmdEvalIpAndMask4, NULL},\r
+               {"DESTIP", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTIP"), CmdEvalIpAndMask4, NULL},\r
+               {"PROTOCOL", CmdPrompt, _UU("CMD_AccessAdd_Prompt_PROTOCOL"), CmdEvalProtocol, NULL},\r
+               {"SRCPORT", CmdPrompt, _UU("CMD_AccessAdd_Prompt_SRCPORT"), CmdEvalPortRange, NULL},\r
+               {"DESTPORT", CmdPrompt, _UU("CMD_AccessAdd_Prompt_DESTPORT"), CmdEvalPortRange, NULL},\r
+               {"TCPSTATE", CmdPrompt, _UU("CMD_AccessAdd_Prompt_TCPSTATE"), CmdEvalTcpState, NULL},\r
+               {"DELAY", CmdPrompt, _UU("CMD_AccessAddEx_Prompt_DELAY"), CmdEvalMinMax, &minmax_delay},\r
+               {"JITTER", CmdPrompt, _UU("CMD_AccessAddEx_Prompt_JITTER"), CmdEvalMinMax, &minmax_jitter},\r
+               {"LOSS", CmdPrompt, _UU("CMD_AccessAddEx_Prompt_LOSS"), CmdEvalMinMax, &minmax_loss},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // サポートしているかどうかチェック\r
+       if (GetCapsBool(ps->CapsList, "b_support_ex_acl") == false)\r
+       {\r
+               c->Write(c, _E(ERR_NOT_SUPPORTED));\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       a = &t.Access;\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       UniStrCpy(a->Note, sizeof(a->Note), GetParamUniStr(o, "MEMO"));\r
+       a->Active = true;\r
+       a->Priority = GetParamInt(o, "PRIORITY");\r
+       a->Discard = StrToPassOrDiscard(GetParamStr(o, "[pass|discard]")) ? false : true;\r
+       StrCpy(a->SrcUsername, sizeof(a->SrcUsername), GetParamStr(o, "SRCUSERNAME"));\r
+       StrCpy(a->DestUsername, sizeof(a->DestUsername), GetParamStr(o, "DESTUSERNAME"));\r
+       ParseMacAddressAndMask(GetParamStr(o, "SRCMAC"), &a->CheckSrcMac, a->SrcMacAddress, a->SrcMacMask);\r
+       ParseMacAddressAndMask(GetParamStr(o, "DESTMAC"), &a->CheckDstMac, a->DstMacAddress, a->DstMacMask);\r
+       ParseIpAndMask4(GetParamStr(o, "SRCIP"), &a->SrcIpAddress, &a->SrcSubnetMask);\r
+       ParseIpAndMask4(GetParamStr(o, "DESTIP"), &a->DestIpAddress, &a->DestSubnetMask);\r
+       a->Protocol = StrToProtocol(GetParamStr(o, "PROTOCOL"));\r
+       ParsePortRange(GetParamStr(o, "SRCPORT"), &a->SrcPortStart, &a->SrcPortEnd);\r
+       ParsePortRange(GetParamStr(o, "DESTPORT"), &a->DestPortStart, &a->DestPortEnd);\r
+       ParseTcpState(GetParamStr(o, "TCPSTATE"), &a->CheckTcpState, &a->Established);\r
+       a->Delay = GetParamInt(o, "DELAY");\r
+       a->Jitter = GetParamInt(o, "JITTER");\r
+       a->Loss = GetParamInt(o, "LOSS");\r
+\r
+       // RPC 呼び出し\r
+       ret = ScAddAccess(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// アクセス リストへのルールの追加 (標準、IPv6)\r
+UINT PsAccessAdd6(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ADD_ACCESS t;\r
+       ACCESS *a;\r
+       IP ip, mask;\r
+       // 指定できるパラメータ リスト\r
+       CMD_EVAL_MIN_MAX minmax =\r
+       {\r
+               "CMD_AccessAdd6_Eval_PRIORITY", 1, 4294967295UL,\r
+       };\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[pass|discard]", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_TYPE"), CmdEvalNotEmpty, NULL},\r
+               {"MEMO", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_MEMO"), NULL, NULL},\r
+               {"PRIORITY", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_PRIORITY"), CmdEvalMinMax, &minmax},\r
+               {"SRCUSERNAME", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCUSERNAME"), NULL, NULL},\r
+               {"DESTUSERNAME", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTUSERNAME"), NULL, NULL},\r
+               {"SRCMAC", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCMAC"), CmdEvalMacAddressAndMask, NULL},\r
+               {"DESTMAC", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTMAC"), CmdEvalMacAddressAndMask, NULL},\r
+               {"SRCIP", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCIP"), CmdEvalIpAndMask6, NULL},\r
+               {"DESTIP", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTIP"), CmdEvalIpAndMask6, NULL},\r
+               {"PROTOCOL", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_PROTOCOL"), CmdEvalProtocol, NULL},\r
+               {"SRCPORT", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCPORT"), CmdEvalPortRange, NULL},\r
+               {"DESTPORT", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTPORT"), CmdEvalPortRange, NULL},\r
+               {"TCPSTATE", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_TCPSTATE"), CmdEvalTcpState, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // サポートしているかどうかチェック\r
+       if (GetCapsBool(ps->CapsList, "b_support_ex_acl") == false)\r
+       {\r
+               c->Write(c, _E(ERR_NOT_SUPPORTED));\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       a = &t.Access;\r
+\r
+       a->IsIPv6 = true;\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       UniStrCpy(a->Note, sizeof(a->Note), GetParamUniStr(o, "MEMO"));\r
+       a->Active = true;\r
+       a->Priority = GetParamInt(o, "PRIORITY");\r
+       a->Discard = StrToPassOrDiscard(GetParamStr(o, "[pass|discard]")) ? false : true;\r
+       StrCpy(a->SrcUsername, sizeof(a->SrcUsername), GetParamStr(o, "SRCUSERNAME"));\r
+       StrCpy(a->DestUsername, sizeof(a->DestUsername), GetParamStr(o, "DESTUSERNAME"));\r
+       ParseMacAddressAndMask(GetParamStr(o, "SRCMAC"), &a->CheckSrcMac, a->SrcMacAddress, a->SrcMacMask);\r
+       ParseMacAddressAndMask(GetParamStr(o, "DESTMAC"), &a->CheckDstMac, a->DstMacAddress, a->DstMacMask);\r
+\r
+       Zero(&ip, sizeof(ip));\r
+       Zero(&mask, sizeof(mask));\r
+\r
+       ParseIpAndMask6(GetParamStr(o, "SRCIP"), &ip, &mask);\r
+       IPToIPv6Addr(&a->SrcIpAddress6, &ip);\r
+       IPToIPv6Addr(&a->SrcSubnetMask6, &mask);\r
+\r
+       ParseIpAndMask6(GetParamStr(o, "DESTIP"), &ip, &mask);\r
+       IPToIPv6Addr(&a->DestIpAddress6, &ip);\r
+       IPToIPv6Addr(&a->DestSubnetMask6, &mask);\r
+\r
+       a->Protocol = StrToProtocol(GetParamStr(o, "PROTOCOL"));\r
+       ParsePortRange(GetParamStr(o, "SRCPORT"), &a->SrcPortStart, &a->SrcPortEnd);\r
+       ParsePortRange(GetParamStr(o, "DESTPORT"), &a->DestPortStart, &a->DestPortEnd);\r
+       ParseTcpState(GetParamStr(o, "TCPSTATE"), &a->CheckTcpState, &a->Established);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScAddAccess(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// アクセス リストへのルールの追加 (拡張、IPv6)\r
+UINT PsAccessAddEx6(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ADD_ACCESS t;\r
+       ACCESS *a;\r
+       IP ip, mask;\r
+       // 指定できるパラメータ リスト\r
+       CMD_EVAL_MIN_MAX minmax =\r
+       {\r
+               "CMD_AccessAdd6_Eval_PRIORITY", 1, 4294967295UL,\r
+       };\r
+       CMD_EVAL_MIN_MAX minmax_delay =\r
+       {\r
+               "CMD_AccessAddEx6_Eval_DELAY", 0, HUB_ACCESSLIST_DELAY_MAX,\r
+       };\r
+       CMD_EVAL_MIN_MAX minmax_jitter =\r
+       {\r
+               "CMD_AccessAddEx6_Eval_JITTER", 0, HUB_ACCESSLIST_JITTER_MAX,\r
+       };\r
+       CMD_EVAL_MIN_MAX minmax_loss =\r
+       {\r
+               "CMD_AccessAddEx6_Eval_LOSS", 0, HUB_ACCESSLIST_LOSS_MAX,\r
+       };\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[pass|discard]", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_TYPE"), CmdEvalNotEmpty, NULL},\r
+               {"MEMO", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_MEMO"), NULL, NULL},\r
+               {"PRIORITY", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_PRIORITY"), CmdEvalMinMax, &minmax},\r
+               {"SRCUSERNAME", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCUSERNAME"), NULL, NULL},\r
+               {"DESTUSERNAME", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTUSERNAME"), NULL, NULL},\r
+               {"SRCMAC", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCMAC"), CmdEvalMacAddressAndMask, NULL},\r
+               {"DESTMAC", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTMAC"), CmdEvalMacAddressAndMask, NULL},\r
+               {"SRCIP", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCIP"), CmdEvalIpAndMask6, NULL},\r
+               {"DESTIP", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTIP"), CmdEvalIpAndMask6, NULL},\r
+               {"PROTOCOL", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_PROTOCOL"), CmdEvalProtocol, NULL},\r
+               {"SRCPORT", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_SRCPORT"), CmdEvalPortRange, NULL},\r
+               {"DESTPORT", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_DESTPORT"), CmdEvalPortRange, NULL},\r
+               {"TCPSTATE", CmdPrompt, _UU("CMD_AccessAdd6_Prompt_TCPSTATE"), CmdEvalTcpState, NULL},\r
+               {"DELAY", CmdPrompt, _UU("CMD_AccessAddEx6_Prompt_DELAY"), CmdEvalMinMax, &minmax_delay},\r
+               {"JITTER", CmdPrompt, _UU("CMD_AccessAddEx6_Prompt_JITTER"), CmdEvalMinMax, &minmax_jitter},\r
+               {"LOSS", CmdPrompt, _UU("CMD_AccessAddEx6_Prompt_LOSS"), CmdEvalMinMax, &minmax_loss},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // サポートしているかどうかチェック\r
+       if (GetCapsBool(ps->CapsList, "b_support_ex_acl") == false)\r
+       {\r
+               c->Write(c, _E(ERR_NOT_SUPPORTED));\r
+               return ERR_NOT_SUPPORTED;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       a = &t.Access;\r
+\r
+       a->IsIPv6 = true;\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       UniStrCpy(a->Note, sizeof(a->Note), GetParamUniStr(o, "MEMO"));\r
+       a->Active = true;\r
+       a->Priority = GetParamInt(o, "PRIORITY");\r
+       a->Discard = StrToPassOrDiscard(GetParamStr(o, "[pass|discard]")) ? false : true;\r
+       StrCpy(a->SrcUsername, sizeof(a->SrcUsername), GetParamStr(o, "SRCUSERNAME"));\r
+       StrCpy(a->DestUsername, sizeof(a->DestUsername), GetParamStr(o, "DESTUSERNAME"));\r
+       ParseMacAddressAndMask(GetParamStr(o, "SRCMAC"), &a->CheckSrcMac, a->SrcMacAddress, a->SrcMacMask);\r
+       ParseMacAddressAndMask(GetParamStr(o, "DESTMAC"), &a->CheckDstMac, a->DstMacAddress, a->DstMacMask);\r
+\r
+       Zero(&ip, sizeof(ip));\r
+       Zero(&mask, sizeof(mask));\r
+\r
+       ParseIpAndMask6(GetParamStr(o, "SRCIP"), &ip, &mask);\r
+       IPToIPv6Addr(&a->SrcIpAddress6, &ip);\r
+       IPToIPv6Addr(&a->SrcSubnetMask6, &mask);\r
+\r
+       ParseIpAndMask6(GetParamStr(o, "DESTIP"), &ip, &mask);\r
+       IPToIPv6Addr(&a->DestIpAddress6, &ip);\r
+       IPToIPv6Addr(&a->DestSubnetMask6, &mask);\r
+\r
+       a->Protocol = StrToProtocol(GetParamStr(o, "PROTOCOL"));\r
+       ParsePortRange(GetParamStr(o, "SRCPORT"), &a->SrcPortStart, &a->SrcPortEnd);\r
+       ParsePortRange(GetParamStr(o, "DESTPORT"), &a->DestPortStart, &a->DestPortEnd);\r
+       ParseTcpState(GetParamStr(o, "TCPSTATE"), &a->CheckTcpState, &a->Established);\r
+       a->Delay = GetParamInt(o, "DELAY");\r
+       a->Jitter = GetParamInt(o, "JITTER");\r
+       a->Loss = GetParamInt(o, "LOSS");\r
+\r
+       // RPC 呼び出し\r
+       ret = ScAddAccess(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+\r
+// アクセス リストのルール一覧の取得\r
+UINT PsAccessList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_ACCESS_LIST t;\r
+       CT *ct;\r
+       UINT i;\r
+       \r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumAccess(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       ct = CtNew();\r
+       CtInsertColumn(ct, _UU("SM_ACCESS_COLUMN_0"), true);\r
+       CtInsertColumn(ct, _UU("SM_ACCESS_COLUMN_1"), true);\r
+       CtInsertColumn(ct, _UU("SM_ACCESS_COLUMN_2"), true);\r
+       CtInsertColumn(ct, _UU("SM_ACCESS_COLUMN_3"), true);\r
+       CtInsertColumn(ct, _UU("SM_ACCESS_COLUMN_5"), false);\r
+       CtInsertColumn(ct, _UU("SM_ACCESS_COLUMN_4"), false);\r
+\r
+       for (i = 0;i < t.NumAccess;i++)\r
+       {\r
+               ACCESS *a = &t.Accesses[i];\r
+               char tmp[MAX_SIZE];\r
+               wchar_t tmp3[MAX_SIZE];\r
+               wchar_t tmp1[MAX_SIZE];\r
+               wchar_t tmp2[MAX_SIZE];\r
+\r
+               GetAccessListStr(tmp, sizeof(tmp), a);\r
+               UniToStru(tmp1, a->Priority);\r
+               StrToUni(tmp2, sizeof(tmp2), tmp);\r
+\r
+               UniToStru(tmp3, a->Id);\r
+\r
+               CtInsert(ct,\r
+                       tmp3,\r
+                       a->Discard ? _UU("SM_ACCESS_DISCARD") : _UU("SM_ACCESS_PASS"),\r
+                       a->Active ? _UU("SM_ACCESS_ENABLE") : _UU("SM_ACCESS_DISABLE"),\r
+                       tmp1,\r
+                       tmp2,\r
+                       a->Note);\r
+       }\r
+\r
+       CtFreeEx(ct, c, true);\r
+\r
+       FreeRpcEnumAccessList(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// アクセス リストからルールを削除\r
+UINT PsAccessDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_DELETE_ACCESS t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[id]", CmdPrompt, _UU("CMD_Access_Prompt_ID"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.Id = GetParamInt(o, "[id]");\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDeleteAccess(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// アクセス リストのルールの有効化\r
+UINT PsAccessEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_ACCESS_LIST t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[id]", CmdPrompt, _UU("CMD_Access_Prompt_ID"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumAccess(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               UINT i;\r
+               bool b = false;\r
+               for (i = 0;i < t.NumAccess;i++)\r
+               {\r
+                       ACCESS *a = &t.Accesses[i];\r
+\r
+                       if (a->Id == GetParamInt(o, "[id]"))\r
+                       {\r
+                               b = true;\r
+\r
+                               a->Active = true;\r
+                       }\r
+               }\r
+\r
+               if (b == false)\r
+               {\r
+                       // 指定した ID が見つからない\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       FreeRpcEnumAccessList(&t);\r
+                       return ret;\r
+               }\r
+\r
+               ret = ScSetAccessList(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcEnumAccessList(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// アクセス リストのルールの無効化\r
+UINT PsAccessDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_ACCESS_LIST t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[id]", CmdPrompt, _UU("CMD_Access_Prompt_ID"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumAccess(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               UINT i;\r
+               bool b = false;\r
+               for (i = 0;i < t.NumAccess;i++)\r
+               {\r
+                       ACCESS *a = &t.Accesses[i];\r
+\r
+                       if (a->Id == GetParamInt(o, "[id]"))\r
+                       {\r
+                               b = true;\r
+\r
+                               a->Active = false;\r
+                       }\r
+               }\r
+\r
+               if (b == false)\r
+               {\r
+                       // 指定した ID が見つからない\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       FreeRpcEnumAccessList(&t);\r
+                       return ret;\r
+               }\r
+\r
+               ret = ScSetAccessList(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               FreeRpcEnumAccessList(&t);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// ユーザー一覧の取得\r
+UINT PsUserList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_USER t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumUser(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               UINT i;\r
+               CT *ct = CtNew();\r
+\r
+               CtInsertColumn(ct, _UU("SM_USER_COLUMN_1"), false);\r
+               CtInsertColumn(ct, _UU("SM_USER_COLUMN_2"), false);\r
+               CtInsertColumn(ct, _UU("SM_USER_COLUMN_3"), false);\r
+               CtInsertColumn(ct, _UU("SM_USER_COLUMN_4"), false);\r
+               CtInsertColumn(ct, _UU("SM_USER_COLUMN_5"), false);\r
+               CtInsertColumn(ct, _UU("SM_USER_COLUMN_6"), false);\r
+               CtInsertColumn(ct, _UU("SM_USER_COLUMN_7"), false);\r
+\r
+               for (i = 0;i < t.NumUser;i++)\r
+               {\r
+                       RPC_ENUM_USER_ITEM *e = &t.Users[i];\r
+                       wchar_t name[MAX_SIZE];\r
+                       wchar_t group[MAX_SIZE];\r
+                       wchar_t num[MAX_SIZE];\r
+                       wchar_t time[MAX_SIZE];\r
+\r
+                       StrToUni(name, sizeof(name), e->Name);\r
+\r
+                       if (StrLen(e->GroupName) != 0)\r
+                       {\r
+                               StrToUni(group, sizeof(group), e->GroupName);\r
+                       }\r
+                       else\r
+                       {\r
+                               UniStrCpy(group, sizeof(group), _UU("SM_NO_GROUP"));\r
+                       }\r
+\r
+                       UniToStru(num, e->NumLogin);\r
+\r
+                       GetDateTimeStrEx64(time, sizeof(time), SystemToLocal64(e->LastLoginTime), NULL);\r
+\r
+                       CtInsert(ct,\r
+                               name, e->Realname, group, e->Note, GetAuthTypeStr(e->AuthType),\r
+                               num, time);\r
+               }\r
+\r
+               CtFreeEx(ct, c, true);\r
+       }\r
+\r
+       FreeRpcEnumUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザー認証方法の文字列の取得\r
+wchar_t *GetAuthTypeStr(UINT id)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       Format(tmp, sizeof(tmp), "SM_AUTHTYPE_%u", id);\r
+\r
+       return _UU(tmp);\r
+}\r
+\r
+// ユーザーの作成\r
+UINT PsUserCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_USER t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"GROUP", CmdPrompt, _UU("CMD_UserCreate_Prompt_GROUP"), NULL, NULL},\r
+               {"REALNAME", CmdPrompt, _UU("CMD_UserCreate_Prompt_REALNAME"), NULL, NULL},\r
+               {"NOTE", CmdPrompt, _UU("CMD_UserCreate_Prompt_NOTE"), NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+       StrCpy(t.GroupName, sizeof(t.GroupName), GetParamStr(o, "GROUP"));\r
+       UniStrCpy(t.Realname, sizeof(t.Realname), GetParamUniStr(o, "REALNAME"));\r
+       UniStrCpy(t.Note, sizeof(t.Note), GetParamUniStr(o, "NOTE"));\r
+\r
+       Trim(t.Name);\r
+       if (StrCmpi(t.Name, "*") == 0)\r
+       {\r
+               t.AuthType = AUTHTYPE_RADIUS;\r
+               t.AuthData = NewRadiusAuthData(NULL);\r
+       }\r
+       else\r
+       {\r
+               UCHAR random_pass[SHA1_SIZE];\r
+\r
+               Rand(random_pass, sizeof(random_pass));\r
+               t.AuthType = AUTHTYPE_PASSWORD;\r
+               t.AuthData = NewPasswordAuthDataRaw(random_pass);\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       ret = ScCreateUser(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザー情報の変更\r
+UINT PsUserSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_USER t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"GROUP", CmdPrompt, _UU("CMD_UserCreate_Prompt_GROUP"), NULL, NULL},\r
+               {"REALNAME", CmdPrompt, _UU("CMD_UserCreate_Prompt_REALNAME"), NULL, NULL},\r
+               {"NOTE", CmdPrompt, _UU("CMD_UserCreate_Prompt_NOTE"), NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       // ユーザーオブジェクトを取得\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       ret = ScGetUser(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       // 情報を更新する\r
+       StrCpy(t.GroupName, sizeof(t.GroupName), GetParamStr(o, "GROUP"));\r
+       UniStrCpy(t.Realname, sizeof(t.Realname), GetParamUniStr(o, "REALNAME"));\r
+       UniStrCpy(t.Note, sizeof(t.Note), GetParamUniStr(o, "NOTE"));\r
+\r
+       // ユーザーオブジェクトを書き込み\r
+       ret = ScSetUser(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザーの削除\r
+UINT PsUserDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_DELETE_USER t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDeleteUser(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザー情報の取得\r
+UINT PsUserGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_USER t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       // ユーザーオブジェクトを取得\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       ret = ScGetUser(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               CT *ct;\r
+\r
+               // ユーザーデータを表示\r
+               ct = CtNewStandard();\r
+\r
+               // ユーザー名\r
+               StrToUni(tmp, sizeof(tmp), t.Name);\r
+               CtInsert(ct, _UU("CMD_UserGet_Column_Name"), tmp);\r
+\r
+               // 本名\r
+               CtInsert(ct, _UU("CMD_UserGet_Column_RealName"), t.Realname);\r
+\r
+               // 説明\r
+               CtInsert(ct, _UU("CMD_UserGet_Column_Note"), t.Note);\r
+\r
+               // グループ名\r
+               if (IsEmptyStr(t.GroupName) == false)\r
+               {\r
+                       StrToUni(tmp, sizeof(tmp), t.GroupName);\r
+                       CtInsert(ct, _UU("CMD_UserGet_Column_Group"), tmp);\r
+               }\r
+\r
+               // 有効期限\r
+               GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.ExpireTime), NULL);\r
+               CtInsert(ct, _UU("CMD_UserGet_Column_Expires"), tmp);\r
+\r
+               // 認証方法\r
+               CtInsert(ct, _UU("CMD_UserGet_Column_AuthType"), GetAuthTypeStr(t.AuthType));\r
+\r
+               switch (t.AuthType)\r
+               {\r
+               case AUTHTYPE_USERCERT:\r
+                       if (t.AuthData != NULL)\r
+                       {\r
+                               AUTHUSERCERT *auc = (AUTHUSERCERT *)t.AuthData;\r
+\r
+                               if (auc != NULL && auc->UserX != NULL)\r
+                               {\r
+                                       // 登録済みユーザー固有証明書\r
+                                       GetAllNameFromX(tmp, sizeof(tmp), auc->UserX);\r
+                                       CtInsert(ct, _UU("CMD_UserGet_Column_UserCert"), tmp);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case AUTHTYPE_ROOTCERT:\r
+                       if (t.AuthData != NULL)\r
+                       {\r
+                               AUTHROOTCERT *arc = (AUTHROOTCERT *)t.AuthData;\r
+\r
+                               if (IsEmptyUniStr(arc->CommonName) == false)\r
+                               {\r
+                                       // 証明書の CN の値の限定\r
+                                       CtInsert(ct, _UU("CMD_UserGet_Column_RootCert_CN"), arc->CommonName);\r
+                               }\r
+\r
+                               if (arc->Serial != NULL && arc->Serial->size >= 1)\r
+                               {\r
+                                       char tmp2[MAX_SIZE];\r
+\r
+                                       // 証明書のシリアル番号の限定\r
+                                       BinToStrEx(tmp2, sizeof(tmp2), arc->Serial->data, arc->Serial->size);\r
+                                       StrToUni(tmp, sizeof(tmp), tmp2);\r
+                                       CtInsert(ct, _UU("CMD_UserGet_Column_RootCert_SERIAL"), tmp);\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case AUTHTYPE_RADIUS:\r
+               case AUTHTYPE_NT:\r
+                       if (t.AuthData != NULL)\r
+                       {\r
+                               AUTHRADIUS *ar = (AUTHRADIUS *)t.AuthData;\r
+\r
+                               // 外部認証サーバーの認証ユーザー名\r
+                               if (IsEmptyUniStr(ar->RadiusUsername) == false)\r
+                               {\r
+                                       CtInsert(ct, _UU("CMD_UserGet_Column_RadiusAlias"), ar->RadiusUsername);\r
+                               }\r
+                       }\r
+                       break;\r
+               }\r
+\r
+               CtInsert(ct, L"---", L"---");\r
+\r
+               GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.CreatedTime), NULL);\r
+               CtInsert(ct, _UU("SM_USERINFO_CREATE"), tmp);\r
+\r
+               GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.UpdatedTime), NULL);\r
+               CtInsert(ct, _UU("SM_USERINFO_UPDATE"), tmp);\r
+\r
+               CmdInsertTrafficInfo(ct, &t.Traffic);\r
+\r
+               UniToStru(tmp, t.NumLogin);\r
+               CtInsert(ct, _UU("SM_USERINFO_NUMLOGIN"), tmp);\r
+\r
+\r
+               CtFree(ct, c);\r
+\r
+               if (t.Policy != NULL)\r
+               {\r
+                       c->Write(c, L"");\r
+                       c->Write(c, _UU("CMD_UserGet_Policy"));\r
+                       PrintPolicy(c, t.Policy, false);\r
+               }\r
+       }\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザーの認証方法を匿名認証に設定\r
+UINT PsUserAnonymousSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_USER t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       // ユーザーオブジェクトを取得\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       ret = ScGetUser(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       // 情報を更新する\r
+       FreeAuthData(t.AuthType, t.AuthData);\r
+\r
+       // 匿名認証に設定する\r
+       t.AuthType = AUTHTYPE_ANONYMOUS;\r
+       t.AuthData = NULL;\r
+\r
+       // ユーザーオブジェクトを書き込み\r
+       ret = ScSetUser(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザーの認証方法をパスワード認証に設定しパスワードを設定\r
+UINT PsUserPasswordSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_USER t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"PASSWORD", CmdPromptChoosePassword, NULL, NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       // ユーザーオブジェクトを取得\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       ret = ScGetUser(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       // 情報を更新する\r
+       FreeAuthData(t.AuthType, t.AuthData);\r
+\r
+       {\r
+               AUTHPASSWORD *pw;\r
+\r
+               pw = NewPasswordAuthData(t.Name, GetParamStr(o, "PASSWORD"));\r
+\r
+               // パスワード認証に設定する\r
+               t.AuthType = AUTHTYPE_PASSWORD;\r
+               t.AuthData = pw;\r
+       }\r
+\r
+       // ユーザーオブジェクトを書き込み\r
+       ret = ScSetUser(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザーの認証方法を固有証明書認証に設定し証明書を設定\r
+UINT PsUserCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_USER t;\r
+       X *x;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"LOADCERT", CmdPrompt, _UU("CMD_LOADCERTPATH"), CmdEvalIsFile, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // 証明書を読み込む\r
+       x = FileToX(GetParamStr(o, "LOADCERT"));\r
+       if (x == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_LOADCERT_FAILED"));\r
+\r
+               FreeParamValueList(o);\r
+\r
+               return ERR_INTERNAL_ERROR;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       // ユーザーオブジェクトを取得\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       ret = ScGetUser(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               FreeX(x);\r
+               return ret;\r
+       }\r
+\r
+       // 情報を更新する\r
+       FreeAuthData(t.AuthType, t.AuthData);\r
+\r
+       {\r
+               AUTHUSERCERT *c;\r
+\r
+               c = NewUserCertAuthData(x);\r
+\r
+               FreeX(x);\r
+\r
+               // パスワード認証に設定する\r
+               t.AuthType = AUTHTYPE_USERCERT;\r
+               t.AuthData = c;\r
+       }\r
+\r
+       // ユーザーオブジェクトを書き込み\r
+       ret = ScSetUser(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 固有証明書認証のユーザーの登録されている証明書の取得\r
+UINT PsUserCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_USER t;\r
+       AUTHUSERCERT *a;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"SAVECERT", CmdPrompt, _UU("CMD_SAVECERTPATH"), NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       // ユーザーオブジェクトを取得\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       ret = ScGetUser(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       a = (AUTHUSERCERT *)t.AuthData;\r
+\r
+       if (t.AuthType != AUTHTYPE_USERCERT || a == NULL || a->UserX == NULL)\r
+       {\r
+               // ユーザーは固有証明書認証ではない\r
+               ret = ERR_INVALID_PARAMETER;\r
+\r
+               c->Write(c, _UU("CMD_UserCertGet_Not_Cert"));\r
+       }\r
+       else\r
+       {\r
+               if (XToFile(a->UserX, GetParamStr(o, "SAVECERT"), true) == false)\r
+               {\r
+                       c->Write(c, _UU("CMD_SAVECERT_FAILED"));\r
+               }\r
+       }\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// ユーザーの認証方法を署名済み証明書認証に設定\r
+UINT PsUserSignedSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_USER t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"CN", CmdPrompt, _UU("CMD_UserSignedSet_Prompt_CN"), NULL, NULL},\r
+               {"SERIAL", CmdPrompt, _UU("CMD_UserSignedSet_Prompt_SERIAL"), NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       // ユーザーオブジェクトを取得\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       ret = ScGetUser(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       // 情報を更新する\r
+       FreeAuthData(t.AuthType, t.AuthData);\r
+\r
+       {\r
+               AUTHROOTCERT *c;\r
+               BUF *b;\r
+               X_SERIAL *serial = NULL;\r
+\r
+               b = StrToBin(GetParamStr(o, "SERIAL"));\r
+\r
+               if (b != NULL && b->Size >= 1)\r
+               {\r
+                       serial = NewXSerial(b->Buf, b->Size);\r
+               }\r
+\r
+               FreeBuf(b);\r
+\r
+               c = NewRootCertAuthData(serial, GetParamUniStr(o, "CN"));\r
+\r
+               FreeXSerial(serial);\r
+\r
+               // パスワード認証に設定する\r
+               t.AuthType = AUTHTYPE_ROOTCERT;\r
+               t.AuthData = c;\r
+       }\r
+\r
+       // ユーザーオブジェクトを書き込み\r
+       ret = ScSetUser(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザーの認証方法を Radius 認証に設定\r
+UINT PsUserRadiusSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_USER t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"ALIAS", CmdPrompt, _UU("CMD_UserRadiusSet_Prompt_ALIAS"), NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       // ユーザーオブジェクトを取得\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       ret = ScGetUser(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       // 情報を更新する\r
+       FreeAuthData(t.AuthType, t.AuthData);\r
+\r
+       {\r
+               AUTHRADIUS *a;\r
+\r
+               a = NewRadiusAuthData(GetParamUniStr(o, "ALIAS"));\r
+\r
+               // Radius 認証に設定する\r
+               t.AuthType = AUTHTYPE_RADIUS;\r
+               t.AuthData = a;\r
+       }\r
+\r
+       // ユーザーオブジェクトを書き込み\r
+       ret = ScSetUser(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザーの認証方法を NT ドメイン認証に設定\r
+UINT PsUserNTLMSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_USER t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"ALIAS", CmdPrompt, _UU("CMD_UserRadiusSet_Prompt_ALIAS"), NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       // ユーザーオブジェクトを取得\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       ret = ScGetUser(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       // 情報を更新する\r
+       FreeAuthData(t.AuthType, t.AuthData);\r
+\r
+       {\r
+               AUTHRADIUS *a;\r
+\r
+               a = NewRadiusAuthData(GetParamUniStr(o, "ALIAS"));\r
+\r
+               // NT ドメイン認証に設定する\r
+               t.AuthType = AUTHTYPE_NT;\r
+               t.AuthData = a;\r
+       }\r
+\r
+       // ユーザーオブジェクトを書き込み\r
+       ret = ScSetUser(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザーのセキュリティ ポリシーの削除\r
+UINT PsUserPolicyRemove(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_USER t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       // ユーザーオブジェクトを取得\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       ret = ScGetUser(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       // 更新\r
+       if (t.Policy != NULL)\r
+       {\r
+               Free(t.Policy);\r
+               t.Policy = NULL;\r
+       }\r
+\r
+       // ユーザーオブジェクトを書き込み\r
+       ret = ScSetUser(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// ユーザーのセキュリティ ポリシーの設定\r
+UINT PsUserPolicySet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_USER t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"NAME", CmdPrompt, _UU("CMD_CascadePolicySet_PROMPT_POLNAME"), CmdEvalNotEmpty, NULL},\r
+               {"VALUE", CmdPrompt, _UU("CMD_CascadePolicySet_PROMPT_POLVALUE"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       // ユーザーオブジェクトを取得\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       ret = ScGetUser(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       // 更新\r
+       if (t.Policy == NULL)\r
+       {\r
+               t.Policy = ClonePolicy(GetDefaultPolicy());\r
+       }\r
+\r
+       // 編集\r
+       if (EditPolicy(c, t.Policy, GetParamStr(o, "NAME"), GetParamStr(o, "VALUE"), false) == false)\r
+       {\r
+               ret = ERR_INVALID_PARAMETER;\r
+       }\r
+       else\r
+       {\r
+               // ユーザーオブジェクトを書き込み\r
+               ret = ScSetUser(ps->Rpc, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+       }\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return ret;\r
+}\r
+\r
+// 文字列を日時に変換\r
+UINT64 StrToDateTime64(char *str)\r
+{\r
+       UINT64 ret = 0;\r
+       TOKEN_LIST *t;\r
+       UINT a, b, c, d, e, f;\r
+       // 引数チェック\r
+       if (str == NULL)\r
+       {\r
+               return INFINITE;\r
+       }\r
+\r
+       if (IsEmptyStr(str) || StrCmpi(str, "none") == 0)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       t = ParseToken(str, ":/,. \"");\r
+       if (t->NumTokens != 6)\r
+       {\r
+               FreeToken(t);\r
+               return INFINITE;\r
+       }\r
+\r
+       a = ToInt(t->Token[0]);\r
+       b = ToInt(t->Token[1]);\r
+       c = ToInt(t->Token[2]);\r
+       d = ToInt(t->Token[3]);\r
+       e = ToInt(t->Token[4]);\r
+       f = ToInt(t->Token[5]);\r
+\r
+       ret = INFINITE;\r
+\r
+       if (a >= 1000 && a <= 9999 && b >= 1 && b <= 12 && c >= 1 && c <= 31 &&\r
+               d >= 0 && d <= 23 && e >= 0 && e <= 59 && f >= 0 && f <= 59)\r
+       {\r
+               SYSTEMTIME t;\r
+\r
+               Zero(&t, sizeof(t));\r
+               t.wYear = a;\r
+               t.wMonth = b;\r
+               t.wDay = c;\r
+               t.wHour = d;\r
+               t.wMinute = e;\r
+               t.wSecond = f;\r
+\r
+               ret = SystemToUINT64(&t);\r
+       }\r
+\r
+       FreeToken(t);\r
+\r
+       return ret;\r
+}\r
+\r
+// 日時文字列の評価\r
+bool CmdEvalDateTime(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       UINT64 ret;\r
+       char tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       UniToStr(tmp, sizeof(tmp), str);\r
+\r
+       ret = StrToDateTime64(tmp);\r
+\r
+       if (ret == INFINITE)\r
+       {\r
+               c->Write(c, _UU("CMD_EVAL_DATE_TIME_FAILED"));\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// ユーザーの有効期限の設定\r
+UINT PsUserExpiresSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_USER t;\r
+       UINT64 expires;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_UserCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"EXPIRES", CmdPrompt, _UU("CMD_UserExpiresSet_Prompt_EXPIRES"), CmdEvalDateTime, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       // ユーザーオブジェクトを取得\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       ret = ScGetUser(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       // 情報を更新する\r
+       expires = StrToDateTime64(GetParamStr(o, "EXPIRES"));\r
+\r
+       if (expires != 0)\r
+       {\r
+               expires = LocalToSystem64(expires);\r
+       }\r
+\r
+       t.ExpireTime = expires;\r
+\r
+       // ユーザーオブジェクトを書き込み\r
+       ret = ScSetUser(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// グループ一覧の取得\r
+UINT PsGroupList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_GROUP t;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumGroup(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct = CtNew();\r
+               UINT i;\r
+\r
+               CtInsertColumn(ct, _UU("SM_GROUPLIST_NAME"), false);\r
+               CtInsertColumn(ct, _UU("SM_GROUPLIST_REALNAME"), false);\r
+               CtInsertColumn(ct, _UU("SM_GROUPLIST_NOTE"), false);\r
+               CtInsertColumn(ct, _UU("SM_GROUPLIST_NUMUSERS"), false);\r
+\r
+               for (i = 0;i < t.NumGroup;i++)\r
+               {\r
+                       wchar_t tmp1[MAX_SIZE];\r
+                       wchar_t tmp2[MAX_SIZE];\r
+                       RPC_ENUM_GROUP_ITEM *e = &t.Groups[i];\r
+\r
+                       StrToUni(tmp1, sizeof(tmp1), e->Name);\r
+                       UniToStru(tmp2, e->NumUsers);\r
+\r
+                       CtInsert(ct, tmp1, e->Realname, e->Note, tmp2);\r
+               }\r
+\r
+               CtFreeEx(ct, c, true);\r
+       }\r
+\r
+       FreeRpcEnumGroup(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// グループの作成\r
+UINT PsGroupCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_GROUP t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"REALNAME", CmdPrompt, _UU("CMD_GroupCreate_Prompt_REALNAME"), NULL, NULL},\r
+               {"NOTE", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NOTE"), NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+       UniStrCpy(t.Realname, sizeof(t.Realname), GetParamUniStr(o, "REALNAME"));\r
+       UniStrCpy(t.Note, sizeof(t.Note), GetParamUniStr(o, "NOTE"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScCreateGroup(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcSetGroup(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// グループ情報の設定\r
+UINT PsGroupSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_GROUP t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"REALNAME", CmdPrompt, _UU("CMD_GroupCreate_Prompt_REALNAME"), NULL, NULL},\r
+               {"NOTE", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NOTE"), NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetGroup(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       // 情報更新\r
+       UniStrCpy(t.Realname, sizeof(t.Realname), GetParamUniStr(o, "REALNAME"));\r
+       UniStrCpy(t.Note, sizeof(t.Note), GetParamUniStr(o, "NOTE"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScSetGroup(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcSetGroup(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// グループの削除\r
+UINT PsGroupDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_DELETE_USER t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDeleteGroup(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// グループ情報と所属しているユーザー一覧の取得\r
+UINT PsGroupGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_GROUP t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetGroup(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               char groupname[MAX_USERNAME_LEN + 1];\r
+               CT *ct = CtNewStandard();\r
+\r
+               StrCpy(groupname, sizeof(groupname), t.Name);\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.Name);\r
+               CtInsert(ct, _UU("CMD_GroupGet_Column_NAME"), tmp);\r
+               CtInsert(ct, _UU("CMD_GroupGet_Column_REALNAME"), t.Realname);\r
+               CtInsert(ct, _UU("CMD_GroupGet_Column_NOTE"), t.Note);\r
+\r
+               CtFree(ct, c);\r
+\r
+               if (t.Policy != NULL)\r
+               {\r
+                       c->Write(c, L"");\r
+                       c->Write(c, _UU("CMD_GroupGet_Column_POLICY"));\r
+\r
+                       PrintPolicy(c, t.Policy, false);\r
+               }\r
+\r
+               {\r
+                       RPC_ENUM_USER t;\r
+                       bool b = false;\r
+\r
+                       Zero(&t, sizeof(t));\r
+\r
+                       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+                       if (ScEnumUser(ps->Rpc, &t) == ERR_NO_ERROR)\r
+                       {\r
+                               UINT i;\r
+\r
+                               for (i = 0;i < t.NumUser;i++)\r
+                               {\r
+                                       RPC_ENUM_USER_ITEM *u = &t.Users[i];\r
+\r
+                                       if (StrCmpi(u->GroupName, groupname) == 0)\r
+                                       {\r
+                                               if (b == false)\r
+                                               {\r
+                                                       b = true;\r
+                                                       c->Write(c, L"");\r
+                                                       c->Write(c, _UU("CMD_GroupGet_Column_MEMBERS"));\r
+                                               }\r
+\r
+                                               UniFormat(tmp, sizeof(tmp), L" %S", u->Name);\r
+                                               c->Write(c, tmp);\r
+                                       }\r
+                               }\r
+                               FreeRpcEnumUser(&t);\r
+\r
+                               if (b)\r
+                               {\r
+                                       c->Write(c, L"");\r
+                               }\r
+                       }\r
+               }\r
+\r
+       }\r
+\r
+       FreeRpcSetGroup(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// グループにユーザーを追加\r
+UINT PsGroupJoin(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_USER t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"USERNAME", CmdPrompt, _UU("CMD_GroupJoin_Prompt_USERNAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "USERNAME"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetUser(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // グループの更新\r
+               StrCpy(t.GroupName, sizeof(t.GroupName), GetParamStr(o, "[name]"));\r
+\r
+               ret = ScSetUser(ps->Rpc, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+       }\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// グループからユーザーを削除\r
+UINT PsGroupUnjoin(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_USER t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_GroupUnjoin_Prompt_name"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetUser(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // グループの更新\r
+               StrCpy(t.GroupName, sizeof(t.GroupName), "");\r
+\r
+               ret = ScSetUser(ps->Rpc, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+       }\r
+\r
+       FreeRpcSetUser(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// グループのセキュリティ ポリシーの削除\r
+UINT PsGroupPolicyRemove(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_GROUP t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetGroup(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // 更新\r
+               if (t.Policy != NULL)\r
+               {\r
+                       Free(t.Policy);\r
+                       t.Policy = NULL;\r
+               }\r
+\r
+               ret = ScSetGroup(ps->Rpc, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+       }\r
+\r
+       FreeRpcSetGroup(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// グループのセキュリティ ポリシーの設定\r
+UINT PsGroupPolicySet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SET_GROUP t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_GroupCreate_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+               {"NAME", CmdPrompt, _UU("CMD_CascadePolicySet_PROMPT_POLNAME"), CmdEvalNotEmpty, NULL},\r
+               {"VALUE", CmdPrompt, _UU("CMD_CascadePolicySet_PROMPT_POLVALUE"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetGroup(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // 更新\r
+               if (t.Policy == NULL)\r
+               {\r
+                       t.Policy = ClonePolicy(GetDefaultPolicy());\r
+               }\r
+\r
+               if (EditPolicy(c, t.Policy, GetParamStr(o, "NAME"), GetParamStr(o, "VALUE"), false) == false)\r
+               {\r
+                       // エラー発生\r
+                       FreeRpcSetGroup(&t);\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ERR_INTERNAL_ERROR;\r
+               }\r
+\r
+               ret = ScSetGroup(ps->Rpc, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+       }\r
+\r
+       FreeRpcSetGroup(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 接続中のセッション一覧の取得\r
+UINT PsSessionList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_SESSION t;\r
+       UINT server_type = 0;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       {\r
+               // サーバー種類の取得\r
+               RPC_SERVER_INFO t;\r
+\r
+               Zero(&t, sizeof(t));\r
+\r
+               if (ScGetServerInfo(ps->Rpc, &t) == ERR_NO_ERROR)\r
+               {\r
+                       server_type = t.ServerType;\r
+\r
+                       FreeRpcServerInfo(&t);\r
+               }\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumSession(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct = CtNew();\r
+               UINT i;\r
+\r
+               CtInsertColumn(ct, _UU("SM_SESS_COLUMN_1"), false);\r
+               CtInsertColumn(ct, _UU("SM_SESS_COLUMN_8"), false);\r
+               CtInsertColumn(ct, _UU("SM_SESS_COLUMN_2"), false);\r
+               CtInsertColumn(ct, _UU("SM_SESS_COLUMN_3"), false);\r
+               CtInsertColumn(ct, _UU("SM_SESS_COLUMN_4"), false);\r
+               CtInsertColumn(ct, _UU("SM_SESS_COLUMN_5"), true);\r
+               CtInsertColumn(ct, _UU("SM_SESS_COLUMN_6"), true);\r
+               CtInsertColumn(ct, _UU("SM_SESS_COLUMN_7"), true);\r
+\r
+               for (i = 0;i < t.NumSession;i++)\r
+               {\r
+                       RPC_ENUM_SESSION_ITEM *e = &t.Sessions[i];\r
+                       wchar_t tmp1[MAX_SIZE];\r
+                       wchar_t *tmp2;\r
+                       wchar_t tmp3[MAX_SIZE];\r
+                       wchar_t tmp4[MAX_SIZE];\r
+                       wchar_t tmp5[MAX_SIZE];\r
+                       wchar_t tmp6[MAX_SIZE];\r
+                       wchar_t tmp7[MAX_SIZE];\r
+                       wchar_t tmp8[MAX_SIZE];\r
+                       bool free_tmp2 = false;\r
+\r
+                       StrToUni(tmp1, sizeof(tmp1), e->Name);\r
+\r
+                       tmp2 = _UU("SM_SESS_NORMAL");\r
+                       if (server_type != SERVER_TYPE_STANDALONE)\r
+                       {\r
+                               if (e->RemoteSession)\r
+                               {\r
+                                       tmp2 = ZeroMalloc(MAX_SIZE);\r
+                                       UniFormat(tmp2, MAX_SIZE, _UU("SM_SESS_REMOTE"), e->RemoteHostname);\r
+                                       free_tmp2 = true;\r
+                               }\r
+                               else\r
+                               {\r
+                                       if (StrLen(e->RemoteHostname) == 0)\r
+                                       {\r
+                                               tmp2 = _UU("SM_SESS_LOCAL");\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               tmp2 = ZeroMalloc(MAX_SIZE);\r
+                                               UniFormat(tmp2, MAX_SIZE, _UU("SM_SESS_LOCAL_2"), e->RemoteHostname);\r
+                                               free_tmp2 = true;\r
+                                       }\r
+                               }\r
+                       }\r
+                       if (e->LinkMode)\r
+                       {\r
+                               if (free_tmp2)\r
+                               {\r
+                                       Free(tmp2);\r
+                                       free_tmp2 = false;\r
+                               }\r
+                               tmp2 = _UU("SM_SESS_LINK");\r
+                       }\r
+                       else if (e->SecureNATMode)\r
+                       {\r
+                               /*if (free_tmp2)\r
+                               {\r
+                                       Free(tmp2);\r
+                                       free_tmp2 = false;\r
+                               }*/\r
+                               tmp2 = _UU("SM_SESS_SNAT");\r
+                       }\r
+\r
+                       StrToUni(tmp3, sizeof(tmp3), e->Username);\r
+\r
+                       StrToUni(tmp4, sizeof(tmp4), e->Hostname);\r
+                       if (e->LinkMode)\r
+                       {\r
+                               UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_LINK_HOSTNAME"));\r
+                       }\r
+                       else if (e->SecureNATMode)\r
+                       {\r
+                               UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_SNAT_HOSTNAME"));\r
+                       }\r
+                       else if (e->BridgeMode)\r
+                       {\r
+                               UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_BRIDGE_HOSTNAME"));\r
+                       }\r
+                       else if (StartWith(e->Username, L3_USERNAME))\r
+                       {\r
+                               UniStrCpy(tmp4, sizeof(tmp4), _UU("SM_SESS_LAYER3_HOSTNAME"));\r
+                       }\r
+\r
+                       UniFormat(tmp5, sizeof(tmp5), L"%u / %u", e->CurrentNumTcp, e->MaxNumTcp);\r
+                       if (e->LinkMode)\r
+                       {\r
+                               UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_SESS_LINK_TCP"));\r
+                       }\r
+                       else if (e->SecureNATMode)\r
+                       {\r
+                               UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_SESS_SNAT_TCP"));\r
+                       }\r
+                       else if (e->BridgeMode)\r
+                       {\r
+                               UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_SESS_BRIDGE_TCP"));\r
+                       }\r
+\r
+                       UniToStr3(tmp6, sizeof(tmp6), e->PacketSize);\r
+                       UniToStr3(tmp7, sizeof(tmp7), e->PacketNum);\r
+\r
+                       if (e->VLanId == 0)\r
+                       {\r
+                               UniStrCpy(tmp8, sizeof(tmp8), _UU("CM_ST_NO_VLAN"));\r
+                       }\r
+                       else\r
+                       {\r
+                               UniToStru(tmp8, e->VLanId);\r
+                       }\r
+\r
+                       CtInsert(ct, tmp1, tmp8, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7);\r
+\r
+                       if (free_tmp2)\r
+                       {\r
+                               Free(tmp2);\r
+                       }\r
+               }\r
+\r
+\r
+               CtFreeEx(ct, c, true);\r
+       }\r
+\r
+       FreeRpcEnumSession(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// NODE_INFO の表示\r
+void CmdPrintNodeInfo(CT *ct, NODE_INFO *info)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       char str[MAX_SIZE];\r
+       // 引数チェック\r
+       if (ct == NULL || info == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       StrToUni(tmp, sizeof(tmp), info->ClientProductName);\r
+       CtInsert(ct, _UU("SM_NODE_CLIENT_NAME"), tmp);\r
+\r
+       UniFormat(tmp, sizeof(tmp), L"%u.%02u", Endian32(info->ClientProductVer) / 100, Endian32(info->ClientProductVer) % 100);\r
+       CtInsert(ct, _UU("SM_NODE_CLIENT_VER"), tmp);\r
+\r
+       UniFormat(tmp, sizeof(tmp), L"Build %u", Endian32(info->ClientProductBuild));\r
+       CtInsert(ct, _UU("SM_NODE_CLIENT_BUILD"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), info->ClientOsName);\r
+       CtInsert(ct, _UU("SM_NODE_CLIENT_OS_NAME"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), info->ClientOsVer);\r
+       CtInsert(ct, _UU("SM_NODE_CLIENT_OS_VER"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), info->ClientOsProductId);\r
+       CtInsert(ct, _UU("SM_NODE_CLIENT_OS_PID"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), info->ClientHostname);\r
+       CtInsert(ct, _UU("SM_NODE_CLIENT_HOST"), tmp);\r
+\r
+       IPToStr4or6(str, sizeof(str), info->ClientIpAddress, info->ClientIpAddress6);\r
+       StrToUni(tmp, sizeof(tmp), str);\r
+       CtInsert(ct, _UU("SM_NODE_CLIENT_IP"), tmp);\r
+\r
+       UniToStru(tmp, Endian32(info->ClientPort));\r
+       CtInsert(ct, _UU("SM_NODE_CLIENT_PORT"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), info->ServerHostname);\r
+       CtInsert(ct, _UU("SM_NODE_SERVER_HOST"), tmp);\r
+\r
+       IPToStr4or6(str, sizeof(str), info->ServerIpAddress, info->ServerIpAddress6);\r
+       StrToUni(tmp, sizeof(tmp), str);\r
+       CtInsert(ct, _UU("SM_NODE_SERVER_IP"), tmp);\r
+\r
+       UniToStru(tmp, Endian32(info->ServerPort));\r
+       CtInsert(ct, _UU("SM_NODE_SERVER_PORT"), tmp);\r
+\r
+       if (StrLen(info->ProxyHostname) != 0)\r
+       {\r
+               StrToUni(tmp, sizeof(tmp), info->ProxyHostname);\r
+               CtInsert(ct, _UU("SM_NODE_PROXY_HOSTNAME"), tmp);\r
+\r
+               IPToStr4or6(str, sizeof(str), info->ProxyIpAddress, info->ProxyIpAddress6);\r
+               StrToUni(tmp, sizeof(tmp), str);\r
+               CtInsert(ct, _UU("SM_NODE_PROXY_IP"), tmp);\r
+\r
+               UniToStru(tmp, Endian32(info->ProxyPort));\r
+               CtInsert(ct, _UU("SM_NODE_PROXY_PORT"), tmp);\r
+       }\r
+}\r
+\r
+// セッション情報の取得\r
+UINT PsSessionGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_SESSION_STATUS t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_SessionGet_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetSessionStatus(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               char str[MAX_SIZE];\r
+               CT *ct = CtNewStandard();\r
+\r
+               if (t.ClientIp != 0)\r
+               {\r
+                       IPToStr4or6(str, sizeof(str), t.ClientIp, t.ClientIp6);\r
+                       StrToUni(tmp, sizeof(tmp), str);\r
+                       CtInsert(ct, _UU("SM_CLIENT_IP"), tmp);\r
+               }\r
+\r
+               if (StrLen(t.ClientHostName) != 0)\r
+               {\r
+                       StrToUni(tmp, sizeof(tmp), t.ClientHostName);\r
+                       CtInsert(ct, _UU("SM_CLIENT_HOSTNAME"), tmp);\r
+               }\r
+\r
+               StrToUni(tmp, sizeof(tmp), t.Username);\r
+               CtInsert(ct, _UU("SM_SESS_STATUS_USERNAME"), tmp);\r
+\r
+               if (StrCmpi(t.Username, LINK_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, SNAT_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, BRIDGE_USER_NAME_PRINT) != 0)\r
+               {\r
+                       StrToUni(tmp, sizeof(tmp), t.RealUsername);\r
+                       CtInsert(ct, _UU("SM_SESS_STATUS_REALUSER"), tmp);\r
+               }\r
+\r
+               if (IsEmptyStr(t.GroupName) == false)\r
+               {\r
+                       StrToUni(tmp, sizeof(tmp), t.GroupName);\r
+                       CtInsert(ct, _UU("SM_SESS_STATUS_GROUPNAME"), tmp);\r
+               }\r
+\r
+\r
+               CmdPrintStatusToListViewEx(ct, &t.Status, true);\r
+\r
+               if (StrCmpi(t.Username, LINK_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, SNAT_USER_NAME_PRINT) != 0 && StrCmpi(t.Username, BRIDGE_USER_NAME_PRINT) != 0 &&\r
+                       StartWith(t.Username, L3_USERNAME) == false)\r
+               {\r
+                       CmdPrintNodeInfo(ct, &t.NodeInfo);\r
+               }\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeRpcSessionStatus(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// セッションの切断\r
+UINT PsSessionDisconnect(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_DELETE_SESSION t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_SessionGet_Prompt_NAME"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       StrCpy(t.Name, sizeof(t.Name), GetParamStr(o, "[name]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDeleteSession(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// MAC アドレス テーブル データベースの取得\r
+UINT PsMacTable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_MAC_TABLE t;\r
+       UINT i;\r
+\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[session_name]", NULL, NULL, NULL, NULL,}\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumMacTable(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct = CtNew();\r
+               char *session_name = GetParamStr(o, "[session_name]");\r
+\r
+               if (IsEmptyStr(session_name))\r
+               {\r
+                       session_name = NULL;\r
+               }\r
+\r
+               CtInsertColumn(ct, _UU("CMD_ID"), false);\r
+               CtInsertColumn(ct, _UU("SM_MAC_COLUMN_1"), false);\r
+               CtInsertColumn(ct, _UU("SM_MAC_COLUMN_1A"), false);\r
+               CtInsertColumn(ct, _UU("SM_MAC_COLUMN_2"), false);\r
+               CtInsertColumn(ct, _UU("SM_MAC_COLUMN_3"), false);\r
+               CtInsertColumn(ct, _UU("SM_MAC_COLUMN_4"), false);\r
+               CtInsertColumn(ct, _UU("SM_MAC_COLUMN_5"), false);\r
+\r
+               for (i = 0;i < t.NumMacTable;i++)\r
+               {\r
+                       char str[MAX_SIZE];\r
+                       wchar_t tmp0[128];\r
+                       wchar_t tmp1[MAX_SIZE];\r
+                       wchar_t tmp2[MAX_SIZE];\r
+                       wchar_t tmp3[MAX_SIZE];\r
+                       wchar_t tmp4[MAX_SIZE];\r
+                       wchar_t tmp5[MAX_SIZE];\r
+                       wchar_t tmp6[MAX_SIZE];\r
+\r
+                       RPC_ENUM_MAC_TABLE_ITEM *e = &t.MacTables[i];\r
+\r
+                       if (session_name == NULL || StrCmpi(e->SessionName, session_name) == 0)\r
+                       {\r
+                               UniToStru(tmp0, e->Key);\r
+\r
+                               StrToUni(tmp1, sizeof(tmp1), e->SessionName);\r
+\r
+                               MacToStr(str, sizeof(str), e->MacAddress);\r
+                               StrToUni(tmp2, sizeof(tmp2), str);\r
+\r
+                               GetDateTimeStr64Uni(tmp3, sizeof(tmp3), SystemToLocal64(e->CreatedTime));\r
+\r
+                               GetDateTimeStr64Uni(tmp4, sizeof(tmp4), SystemToLocal64(e->UpdatedTime));\r
+\r
+                               if (StrLen(e->RemoteHostname) == 0)\r
+                               {\r
+                                       UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_MACIP_LOCAL"));\r
+                               }\r
+                               else\r
+                               {\r
+                                       UniFormat(tmp5, sizeof(tmp5), _UU("SM_MACIP_SERVER"), e->RemoteHostname);\r
+                               }\r
+\r
+                               UniToStru(tmp6, e->VlanId);\r
+                               if (e->VlanId == 0)\r
+                               {\r
+                                       UniStrCpy(tmp6, sizeof(tmp6), _UU("CM_ST_NONE"));\r
+                               }\r
+\r
+                               CtInsert(ct,\r
+                                       tmp0, tmp1, tmp6, tmp2, tmp3, tmp4, tmp5);\r
+                       }\r
+               }\r
+\r
+               CtFreeEx(ct, c, true);\r
+       }\r
+\r
+       FreeRpcEnumMacTable(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// MAC アドレス テーブル エントリの削除\r
+UINT PsMacDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_DELETE_TABLE t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[id]", CmdPrompt, _UU("CMD_MacDelete_Prompt"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.Key = GetParamInt(o, "[id]");\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDeleteMacTable(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// IP アドレス テーブル データベースの取得\r
+UINT PsIpTable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_IP_TABLE t;\r
+       UINT i;\r
+\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[session_name]", NULL, NULL, NULL, NULL,}\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumIpTable(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct = CtNew();\r
+               char *session_name = GetParamStr(o, "[session_name]");\r
+\r
+               if (IsEmptyStr(session_name))\r
+               {\r
+                       session_name = NULL;\r
+               }\r
+\r
+               CtInsertColumn(ct, _UU("CMD_ID"), false);\r
+               CtInsertColumn(ct, _UU("SM_IP_COLUMN_1"), false);\r
+               CtInsertColumn(ct, _UU("SM_IP_COLUMN_2"), false);\r
+               CtInsertColumn(ct, _UU("SM_IP_COLUMN_3"), false);\r
+               CtInsertColumn(ct, _UU("SM_IP_COLUMN_4"), false);\r
+               CtInsertColumn(ct, _UU("SM_IP_COLUMN_5"), false);\r
+\r
+               for (i = 0;i < t.NumIpTable;i++)\r
+               {\r
+                       char str[MAX_SIZE];\r
+                       wchar_t tmp0[128];\r
+                       wchar_t tmp1[MAX_SIZE];\r
+                       wchar_t tmp2[MAX_SIZE];\r
+                       wchar_t tmp3[MAX_SIZE];\r
+                       wchar_t tmp4[MAX_SIZE];\r
+                       wchar_t tmp5[MAX_SIZE];\r
+                       RPC_ENUM_IP_TABLE_ITEM *e = &t.IpTables[i];\r
+\r
+                       if (session_name == NULL || StrCmpi(e->SessionName, session_name) == 0)\r
+                       {\r
+                               UniToStru(tmp0, e->Key);\r
+\r
+                               StrToUni(tmp1, sizeof(tmp1), e->SessionName);\r
+\r
+                               if (e->DhcpAllocated == false)\r
+                               {\r
+                                       IPToStr(str, sizeof(str), &e->IpV6);\r
+                                       StrToUni(tmp2, sizeof(tmp2), str);\r
+                               }\r
+                               else\r
+                               {\r
+                                       IPToStr(str, sizeof(str), &e->IpV6);\r
+                                       UniFormat(tmp2, sizeof(tmp2), _UU("SM_MAC_IP_DHCP"), str);\r
+                               }\r
+\r
+                               GetDateTimeStr64Uni(tmp3, sizeof(tmp3), SystemToLocal64(e->CreatedTime));\r
+\r
+                               GetDateTimeStr64Uni(tmp4, sizeof(tmp4), SystemToLocal64(e->UpdatedTime));\r
+\r
+                               if (StrLen(e->RemoteHostname) == 0)\r
+                               {\r
+                                       UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_MACIP_LOCAL"));\r
+                               }\r
+                               else\r
+                               {\r
+                                       UniFormat(tmp5, sizeof(tmp5), _UU("SM_MACIP_SERVER"), e->RemoteHostname);\r
+                               }\r
+\r
+                               CtInsert(ct,\r
+                                       tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);\r
+                       }\r
+               }\r
+\r
+               CtFreeEx(ct, c, true);\r
+       }\r
+\r
+       FreeRpcEnumIpTable(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// IP アドレス テーブル エントリの削除\r
+UINT PsIpDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_DELETE_TABLE t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[id]", CmdPrompt, _UU("CMD_MacDelete_Prompt"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.Key = GetParamInt(o, "[id]");\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDeleteIpTable(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 NAT および DHCP サーバー機能 (SecureNAT 機能) の有効化\r
+UINT PsSecureNatEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_HUB t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnableSecureNAT(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 NAT および DHCP サーバー機能 (SecureNAT 機能) の無効化\r
+UINT PsSecureNatDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_HUB t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDisableSecureNAT(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 NAT および DHCP サーバー機能 (SecureNAT 機能) の動作状況の取得\r
+UINT PsSecureNatStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_NAT_STATUS t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetSecureNATStatus(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               CT *ct = CtNewStandard();\r
+\r
+               StrToUni(tmp, sizeof(tmp), ps->HubName);\r
+               CtInsert(ct, _UU("SM_HUB_COLUMN_1"), tmp);\r
+\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumTcpSessions);\r
+               CtInsert(ct, _UU("NM_STATUS_TCP"), tmp);\r
+\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumUdpSessions);\r
+               CtInsert(ct, _UU("NM_STATUS_UDP"), tmp);\r
+\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_CLIENT"), t.NumDhcpClients);\r
+               CtInsert(ct, _UU("NM_STATUS_DHCP"), tmp);\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeRpcNatStatus(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// SecureNAT 機能の仮想ホストのネットワーク インターフェイス設定の取得\r
+UINT PsSecureNatHostGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       VH_OPTION t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetSecureNATOption(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               char str[MAX_SIZE];\r
+               CT *ct = CtNewStandard();\r
+\r
+               // 使用フラグ\r
+               // MAC アドレス\r
+               MacToStr(str, sizeof(str), t.MacAddress);\r
+               StrToUni(tmp, sizeof(tmp), str);\r
+               CtInsert(ct, _UU("CMD_SecureNatHostGet_Column_MAC"), tmp);\r
+\r
+               // IP アドレス\r
+               IPToUniStr(tmp, sizeof(tmp), &t.Ip);\r
+               CtInsert(ct, _UU("CMD_SecureNatHostGet_Column_IP"), tmp);\r
+\r
+               // サブネット マスク\r
+               IPToUniStr(tmp, sizeof(tmp), &t.Mask);\r
+               CtInsert(ct, _UU("CMD_SecureNatHostGet_Column_MASK"), tmp);\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// SecureNAT 機能の仮想ホストのネットワーク インターフェイス設定の変更\r
+UINT PsSecureNatHostSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       VH_OPTION t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"MAC", CmdPrompt, _UU("CMD_SecureNatHostSet_Prompt_MAC"), NULL, NULL},\r
+               {"IP", CmdPrompt, _UU("CMD_SecureNatHostSet_Prompt_IP"), CmdEvalIp, NULL},\r
+               {"MASK", CmdPrompt, _UU("CMD_SecureNatHostSet_Prompt_MASK"), CmdEvalIp, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetSecureNATOption(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               char *mac, *ip, *mask;\r
+               bool ok = true;\r
+\r
+               StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+               mac = GetParamStr(o, "MAC");\r
+               ip = GetParamStr(o, "IP");\r
+               mask = GetParamStr(o, "MASK");\r
+\r
+               if (IsEmptyStr(mac) == false)\r
+               {\r
+                       BUF *b = StrToBin(mac);\r
+\r
+                       if (b == NULL || b->Size != 6)\r
+                       {\r
+                               ok = false;\r
+                       }\r
+                       else\r
+                       {\r
+                               Copy(t.MacAddress, b->Buf, 6);\r
+                       }\r
+\r
+                       FreeBuf(b);\r
+               }\r
+\r
+               if (IsEmptyStr(ip) == false)\r
+               {\r
+                       if (IsIpStr4(ip) == false)\r
+                       {\r
+                               ok = false;\r
+                       }\r
+                       else\r
+                       {\r
+                               UINT u = StrToIP32(ip);\r
+\r
+                               if (u == 0 || u == 0xffffffff)\r
+                               {\r
+                                       ok = false;\r
+                               }\r
+                               else\r
+                               {\r
+                                       UINTToIP(&t.Ip, u);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if (IsEmptyStr(mask) == false)\r
+               {\r
+                       if (IsIpStr4(mask) == false)\r
+                       {\r
+                               ok = false;\r
+                       }\r
+                       else\r
+                       {\r
+                               StrToIP(&t.Mask, mask);\r
+                       }\r
+               }\r
+\r
+               if (ok == false)\r
+               {\r
+                       // パラメータが不正\r
+                       ret = ERR_INVALID_PARAMETER;\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+               else\r
+               {\r
+                       ret = ScSetSecureNATOption(ps->Rpc, &t);\r
+\r
+                       if (ret != ERR_NO_ERROR)\r
+                       {\r
+                               // エラー発生\r
+                               CmdPrintError(c, ret);\r
+                               FreeParamValueList(o);\r
+                               return ret;\r
+                       }\r
+               }\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// SecureNAT 機能の仮想 NAT 機能の設定の取得\r
+UINT PsNatGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       VH_OPTION t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetSecureNATOption(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               CT *ct = CtNewStandard();\r
+\r
+               // 仮想 NAT 機能を使用する\r
+               CtInsert(ct, _UU("CMD_NatGet_Column_USE"), t.UseNat ? _UU("SEC_YES") : _UU("SEC_NO"));\r
+\r
+               // MTU 値\r
+               UniToStru(tmp, t.Mtu);\r
+               CtInsert(ct, _UU("CMD_NetGet_Column_MTU"), tmp);\r
+\r
+               // TCP セッションのタイムアウト (秒)\r
+               UniToStru(tmp, t.NatTcpTimeout);\r
+               CtInsert(ct, _UU("CMD_NatGet_Column_TCP"), tmp);\r
+\r
+               // UDP セッションのタイムアウト (秒)\r
+               UniToStru(tmp, t.NatUdpTimeout);\r
+               CtInsert(ct, _UU("CMD_NatGet_Column_UDP"), tmp);\r
+\r
+               // ログ保存\r
+               CtInsert(ct, _UU("CMD_SecureNatHostGet_Column_LOG"), t.SaveLog ? _UU("SEC_YES") : _UU("SEC_NO"));\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// SecureNAT 機能の仮想 NAT 機能の有効化\r
+UINT PsNatEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       VH_OPTION t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetSecureNATOption(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               bool ok = true;\r
+\r
+               t.UseNat = true;\r
+\r
+               if (ok == false)\r
+               {\r
+                       // パラメータが不正\r
+                       ret = ERR_INVALID_PARAMETER;\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+               else\r
+               {\r
+                       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+                       ret = ScSetSecureNATOption(ps->Rpc, &t);\r
+\r
+                       if (ret != ERR_NO_ERROR)\r
+                       {\r
+                               // エラー発生\r
+                               CmdPrintError(c, ret);\r
+                               FreeParamValueList(o);\r
+                               return ret;\r
+                       }\r
+               }\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// SecureNAT 機能の仮想 NAT 機能の無効化\r
+UINT PsNatDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       VH_OPTION t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetSecureNATOption(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               bool ok = true;\r
+\r
+               t.UseNat = false;\r
+\r
+               if (ok == false)\r
+               {\r
+                       // パラメータが不正\r
+                       ret = ERR_INVALID_PARAMETER;\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+               else\r
+               {\r
+                       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+                       ret = ScSetSecureNATOption(ps->Rpc, &t);\r
+\r
+                       if (ret != ERR_NO_ERROR)\r
+                       {\r
+                               // エラー発生\r
+                               CmdPrintError(c, ret);\r
+                               FreeParamValueList(o);\r
+                               return ret;\r
+                       }\r
+               }\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// SecureNAT 機能の仮想 NAT 機能の設定の変更\r
+UINT PsNatSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       VH_OPTION t;\r
+       // 指定できるパラメータ リスト\r
+       CMD_EVAL_MIN_MAX mtu_mm =\r
+       {\r
+               "CMD_NatSet_Eval_MTU", TCP_HEADER_SIZE + IP_HEADER_SIZE + MAC_HEADER_SIZE + 8, MAX_L3_DATA_SIZE,\r
+       };\r
+       CMD_EVAL_MIN_MAX tcp_mm =\r
+       {\r
+               "CMD_NatSet_Eval_TCP", NAT_TCP_MIN_TIMEOUT / 1000, NAT_TCP_MAX_TIMEOUT / 1000,\r
+       };\r
+       CMD_EVAL_MIN_MAX udp_mm =\r
+       {\r
+               "CMD_NatSet_Eval_UDP", NAT_UDP_MIN_TIMEOUT / 1000, NAT_UDP_MAX_TIMEOUT / 1000,\r
+       };\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"MTU", CmdPrompt, _UU("CMD_NatSet_Prompt_MTU"), CmdEvalMinMax, &mtu_mm},\r
+               {"TCPTIMEOUT", CmdPrompt, _UU("CMD_NatSet_Prompt_TCPTIMEOUT"), CmdEvalMinMax, &tcp_mm},\r
+               {"UDPTIMEOUT", CmdPrompt, _UU("CMD_NatSet_Prompt_UDPTIMEOUT"), CmdEvalMinMax, &udp_mm},\r
+               {"LOG", CmdPrompt, _UU("CMD_NatSet_Prompt_LOG"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetSecureNATOption(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               bool ok = true;\r
+\r
+               t.Mtu = GetParamInt(o, "MTU");\r
+               t.NatTcpTimeout = GetParamInt(o, "TCPTIMEOUT");\r
+               t.NatUdpTimeout = GetParamInt(o, "UDPTIMEOUT");\r
+               t.SaveLog = GetParamYes(o, "LOG");\r
+\r
+               if (ok == false)\r
+               {\r
+                       // パラメータが不正\r
+                       ret = ERR_INVALID_PARAMETER;\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+               else\r
+               {\r
+                       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+                       ret = ScSetSecureNATOption(ps->Rpc, &t);\r
+\r
+                       if (ret != ERR_NO_ERROR)\r
+                       {\r
+                               // エラー発生\r
+                               CmdPrintError(c, ret);\r
+                               FreeParamValueList(o);\r
+                               return ret;\r
+                       }\r
+               }\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// SecureNAT 機能の仮想 NAT 機能のセッション テーブルの取得\r
+UINT PsNatTable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_NAT t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumNAT(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct = CtNew();\r
+               UINT i;\r
+\r
+               CtInsertColumn(ct, _UU("NM_NAT_ID"), false);\r
+               CtInsertColumn(ct, _UU("NM_NAT_PROTOCOL"), false);\r
+               CtInsertColumn(ct, _UU("NM_NAT_SRC_HOST"), false);\r
+               CtInsertColumn(ct, _UU("NM_NAT_SRC_PORT"), false);\r
+               CtInsertColumn(ct, _UU("NM_NAT_DST_HOST"), false);\r
+               CtInsertColumn(ct, _UU("NM_NAT_DST_PORT"), false);\r
+               CtInsertColumn(ct, _UU("NM_NAT_CREATED"), false);\r
+               CtInsertColumn(ct, _UU("NM_NAT_LAST_COMM"), false);\r
+               CtInsertColumn(ct, _UU("NM_NAT_SIZE"), false);\r
+               CtInsertColumn(ct, _UU("NM_NAT_TCP_STATUS"), false);\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       RPC_ENUM_NAT_ITEM *e = &t.Items[i];\r
+                       wchar_t tmp0[MAX_SIZE];\r
+                       wchar_t *tmp1 = L"";\r
+                       wchar_t tmp2[MAX_SIZE];\r
+                       wchar_t tmp3[MAX_SIZE];\r
+                       wchar_t tmp4[MAX_SIZE];\r
+                       wchar_t tmp5[MAX_SIZE];\r
+                       wchar_t tmp6[MAX_SIZE];\r
+                       wchar_t tmp7[MAX_SIZE];\r
+                       wchar_t tmp8[MAX_SIZE];\r
+                       wchar_t *tmp9 = L"";\r
+                       char v1[128], v2[128];\r
+\r
+                       // ID\r
+                       UniToStru(tmp0, e->Id);\r
+\r
+                       // プロトコル\r
+                       switch (e->Protocol)\r
+                       {\r
+                       case NAT_TCP:\r
+                               tmp1 = _UU("NM_NAT_PROTO_TCP");\r
+                               break;\r
+                       case NAT_UDP:\r
+                               tmp1 = _UU("NM_NAT_PROTO_UDP");\r
+                               break;\r
+                       case NAT_DNS:\r
+                               tmp1 = _UU("NM_NAT_PROTO_DNS");\r
+                               break;\r
+                       }\r
+\r
+                       // 接続元ホスト\r
+                       StrToUni(tmp2, sizeof(tmp2), e->SrcHost);\r
+\r
+                       // 接続元ポート\r
+                       UniToStru(tmp3, e->SrcPort);\r
+\r
+                       // 接続先ホスト\r
+                       StrToUni(tmp4, sizeof(tmp4), e->DestHost);\r
+\r
+                       // 接続先ポート\r
+                       UniToStru(tmp5, e->DestPort);\r
+\r
+                       // セッション作成日時\r
+                       GetDateTimeStrEx64(tmp6, sizeof(tmp6), SystemToLocal64(e->CreatedTime), NULL);\r
+\r
+                       // 最終通信日時\r
+                       GetDateTimeStrEx64(tmp7, sizeof(tmp7), SystemToLocal64(e->LastCommTime), NULL);\r
+\r
+                       // 通信量\r
+                       ToStr3(v1, sizeof(v1), e->RecvSize);\r
+                       ToStr3(v2, sizeof(v2), e->SendSize);\r
+                       UniFormat(tmp8, sizeof(tmp8), L"%S / %S", v1, v2);\r
+\r
+                       // TCP 状態\r
+                       if (e->Protocol == NAT_TCP)\r
+                       {\r
+                               switch (e->TcpStatus)\r
+                               {\r
+                               case NAT_TCP_CONNECTING:\r
+                                       tmp9 = _UU("NAT_TCP_CONNECTING");\r
+                                       break;\r
+                               case NAT_TCP_SEND_RESET:\r
+                                       tmp9 = _UU("NAT_TCP_SEND_RESET");\r
+                                       break;\r
+                               case NAT_TCP_CONNECTED:\r
+                                       tmp9 = _UU("NAT_TCP_CONNECTED");\r
+                                       break;\r
+                               case NAT_TCP_ESTABLISHED:\r
+                                       tmp9 = _UU("NAT_TCP_ESTABLISHED");\r
+                                       break;\r
+                               case NAT_TCP_WAIT_DISCONNECT:\r
+                                       tmp9 = _UU("NAT_TCP_WAIT_DISCONNECT");\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       CtInsert(ct,\r
+                               tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9);\r
+               }\r
+\r
+               CtFreeEx(ct, c, true);\r
+       }\r
+\r
+       FreeRpcEnumNat(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// SecureNAT 機能の仮想 DHCP サーバー機能の設定の取得\r
+UINT PsDhcpGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       VH_OPTION t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetSecureNATOption(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               CT *ct = CtNewStandard();\r
+\r
+               // 仮想 DHCP 機能を使用する\r
+               CtInsert(ct, _UU("CMD_DhcpGet_Column_USE"), t.UseDhcp ? _UU("SEC_YES") : _UU("SEC_NO"));\r
+\r
+               // 配布アドレス帯の開始\r
+               IPToUniStr(tmp, sizeof(tmp), &t.DhcpLeaseIPStart);\r
+               CtInsert(ct, _UU("CMD_DhcpGet_Column_IP1"), tmp);\r
+\r
+               // 配布アドレス帯の終了\r
+               IPToUniStr(tmp, sizeof(tmp), &t.DhcpLeaseIPEnd);\r
+               CtInsert(ct, _UU("CMD_DhcpGet_Column_IP2"), tmp);\r
+\r
+               // サブネット マスク\r
+               IPToUniStr(tmp, sizeof(tmp), &t.DhcpSubnetMask);\r
+               CtInsert(ct, _UU("CMD_DhcpGet_Column_MASK"), tmp);\r
+\r
+               // リース期限 (秒)\r
+               UniToStru(tmp, t.DhcpExpireTimeSpan);\r
+               CtInsert(ct, _UU("CMD_DhcpGet_Column_LEASE"), tmp);\r
+\r
+               // デフォルトゲートウェイアドレス\r
+               UniStrCpy(tmp, sizeof(tmp), _UU("SEC_NONE"));\r
+               if (IPToUINT(&t.DhcpGatewayAddress) != 0)\r
+               {\r
+                       IPToUniStr(tmp, sizeof(tmp), &t.DhcpGatewayAddress);\r
+               }\r
+               CtInsert(ct, _UU("CMD_DhcpGet_Column_GW"), tmp);\r
+\r
+               // DNS サーバー アドレス\r
+               UniStrCpy(tmp, sizeof(tmp), _UU("SEC_NONE"));\r
+               if (IPToUINT(&t.DhcpDnsServerAddress) != 0)\r
+               {\r
+                       IPToUniStr(tmp, sizeof(tmp), &t.DhcpDnsServerAddress);\r
+               }\r
+               CtInsert(ct, _UU("CMD_DhcpGet_Column_DNS"), tmp);\r
+\r
+               // ドメイン名\r
+               StrToUni(tmp, sizeof(tmp), t.DhcpDomainName);\r
+               CtInsert(ct, _UU("CMD_DhcpGet_Column_DOMAIN"), tmp);\r
+\r
+               // ログ保存\r
+               CtInsert(ct, _UU("CMD_SecureNatHostGet_Column_LOG"), t.SaveLog ? _UU("SEC_YES") : _UU("SEC_NO"));\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// SecureNAT 機能の仮想 DHCP サーバー機能の有効化\r
+UINT PsDhcpEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       VH_OPTION t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetSecureNATOption(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               bool ok = true;\r
+\r
+               t.UseDhcp = true;\r
+\r
+               if (ok == false)\r
+               {\r
+                       // パラメータが不正\r
+                       ret = ERR_INVALID_PARAMETER;\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+               else\r
+               {\r
+                       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+                       ret = ScSetSecureNATOption(ps->Rpc, &t);\r
+\r
+                       if (ret != ERR_NO_ERROR)\r
+                       {\r
+                               // エラー発生\r
+                               CmdPrintError(c, ret);\r
+                               FreeParamValueList(o);\r
+                               return ret;\r
+                       }\r
+               }\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// SecureNAT 機能の仮想 DHCP サーバー機能の無効化\r
+UINT PsDhcpDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       VH_OPTION t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetSecureNATOption(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               bool ok = true;\r
+\r
+               t.UseDhcp = false;\r
+\r
+               if (ok == false)\r
+               {\r
+                       // パラメータが不正\r
+                       ret = ERR_INVALID_PARAMETER;\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+               else\r
+               {\r
+                       ret = ScSetSecureNATOption(ps->Rpc, &t);\r
+\r
+                       if (ret != ERR_NO_ERROR)\r
+                       {\r
+                               // エラー発生\r
+                               CmdPrintError(c, ret);\r
+                               FreeParamValueList(o);\r
+                               return ret;\r
+                       }\r
+               }\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// SecureNAT 機能の仮想 DHCP サーバー機能の設定の変更\r
+UINT PsDhcpSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       VH_OPTION t;\r
+       // 指定できるパラメータ リスト\r
+       CMD_EVAL_MIN_MAX mm =\r
+       {\r
+               "CMD_NatSet_Eval_UDP", NAT_UDP_MIN_TIMEOUT / 1000, NAT_UDP_MAX_TIMEOUT / 1000,\r
+       };\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"START", CmdPrompt, _UU("CMD_DhcpSet_Prompt_START"), CmdEvalIp, NULL},\r
+               {"END", CmdPrompt, _UU("CMD_DhcpSet_Prompt_END"), CmdEvalIp, NULL},\r
+               {"MASK", CmdPrompt, _UU("CMD_DhcpSet_Prompt_MASK"), CmdEvalIp, NULL},\r
+               {"EXPIRE", CmdPrompt, _UU("CMD_DhcpSet_Prompt_EXPIRE"), CmdEvalMinMax, &mm},\r
+               {"GW", CmdPrompt, _UU("CMD_DhcpSet_Prompt_GW"), CmdEvalIp, NULL},\r
+               {"DNS", CmdPrompt, _UU("CMD_DhcpSet_Prompt_DNS"), CmdEvalIp, NULL},\r
+               {"DOMAIN", CmdPrompt, _UU("CMD_DhcpSet_Prompt_DOMAIN"), NULL, NULL},\r
+               {"LOG", CmdPrompt, _UU("CMD_NatSet_Prompt_LOG"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetSecureNATOption(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               bool ok = true;\r
+\r
+               StrToIP(&t.DhcpLeaseIPStart, GetParamStr(o, "START"));\r
+               StrToIP(&t.DhcpLeaseIPEnd, GetParamStr(o, "END"));\r
+               StrToIP(&t.DhcpSubnetMask, GetParamStr(o, "MASK"));\r
+               t.DhcpExpireTimeSpan = GetParamInt(o, "EXPIRE");\r
+               StrToIP(&t.DhcpGatewayAddress, GetParamStr(o, "GW"));\r
+               StrToIP(&t.DhcpDnsServerAddress, GetParamStr(o, "DNS"));\r
+               StrCpy(t.DhcpDomainName, sizeof(t.DhcpDomainName), GetParamStr(o, "DOMAIN"));\r
+               t.SaveLog = GetParamYes(o, "LOG");\r
+\r
+               if (ok == false)\r
+               {\r
+                       // パラメータが不正\r
+                       ret = ERR_INVALID_PARAMETER;\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+               else\r
+               {\r
+                       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+                       ret = ScSetSecureNATOption(ps->Rpc, &t);\r
+\r
+                       if (ret != ERR_NO_ERROR)\r
+                       {\r
+                               // エラー発生\r
+                               CmdPrintError(c, ret);\r
+                               FreeParamValueList(o);\r
+                               return ret;\r
+                       }\r
+               }\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// SecureNAT 機能の仮想 DHCP サーバー機能のリース テーブルの取得\r
+UINT PsDhcpTable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_DHCP t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumDHCP(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct = CtNew();\r
+               UINT i;\r
+\r
+               CtInsertColumn(ct, _UU("DHCP_DHCP_ID"), false);\r
+               CtInsertColumn(ct, _UU("DHCP_LEASED_TIME"), false);\r
+               CtInsertColumn(ct, _UU("DHCP_EXPIRE_TIME"), false);\r
+               CtInsertColumn(ct, _UU("DHCP_MAC_ADDRESS"), false);\r
+               CtInsertColumn(ct, _UU("DHCP_IP_ADDRESS"), false);\r
+               CtInsertColumn(ct, _UU("DHCP_HOSTNAME"), false);\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       RPC_ENUM_DHCP_ITEM *e = &t.Items[i];\r
+                       wchar_t tmp0[MAX_SIZE];\r
+                       wchar_t tmp1[MAX_SIZE];\r
+                       wchar_t tmp2[MAX_SIZE];\r
+                       wchar_t tmp3[MAX_SIZE];\r
+                       wchar_t tmp4[MAX_SIZE];\r
+                       wchar_t tmp5[MAX_SIZE];\r
+                       char str[MAX_SIZE];\r
+\r
+                       // ID\r
+                       UniToStru(tmp0, e->Id);\r
+\r
+                       // 時刻\r
+                       GetDateTimeStrEx64(tmp1, sizeof(tmp1), SystemToLocal64(e->LeasedTime), NULL);\r
+                       GetDateTimeStrEx64(tmp2, sizeof(tmp2), SystemToLocal64(e->ExpireTime), NULL);\r
+\r
+                       MacToStr(str, sizeof(str), e->MacAddress);\r
+                       StrToUni(tmp3, sizeof(tmp3), str);\r
+\r
+                       IPToStr32(str, sizeof(str), e->IpAddress);\r
+                       StrToUni(tmp4, sizeof(tmp4), str);\r
+\r
+                       StrToUni(tmp5, sizeof(tmp5), e->Hostname);\r
+\r
+                       CtInsert(ct,\r
+                               tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);\r
+               }\r
+\r
+               CtFreeEx(ct, c, true);\r
+       }\r
+\r
+       FreeRpcEnumDhcp(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB 管理オプションの一覧の取得\r
+UINT PsAdminOptionList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ADMIN_OPTION t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetHubAdminOptions(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct = CtNewStandardEx();\r
+               UINT i;\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       ADMIN_OPTION *e = &t.Items[i];\r
+                       wchar_t tmp1[MAX_SIZE];\r
+                       wchar_t tmp2[MAX_SIZE];\r
+\r
+                       StrToUni(tmp1, sizeof(tmp1), e->Name);\r
+                       UniToStru(tmp2, e->Value);\r
+\r
+                       CtInsert(ct, tmp1, tmp2, GetHubAdminOptionHelpString(e->Name));\r
+                               \r
+               }\r
+\r
+               CtFreeEx(ct, c, true);\r
+       }\r
+\r
+       FreeRpcAdminOption(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB 管理オプションの値の設定\r
+UINT PsAdminOptionSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ADMIN_OPTION t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_AdminOptionSet_Prompt_name"), CmdEvalNotEmpty, NULL},\r
+               {"VALUE", CmdPrompt, _UU("CMD_AdminOptionSet_Prompt_VALUE"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetHubAdminOptions(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               UINT i;\r
+               bool b = false;\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       if (StrCmpi(t.Items[i].Name, GetParamStr(o, "[name]")) == 0)\r
+                       {\r
+                               t.Items[i].Value = GetParamInt(o, "VALUE");\r
+                               b = true;\r
+                       }\r
+               }\r
+\r
+               if (b == false)\r
+               {\r
+                       // エラー発生\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       FreeRpcAdminOption(&t);\r
+                       return ret;\r
+               }\r
+               else\r
+               {\r
+                       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+                       ret = ScSetHubAdminOptions(ps->Rpc, &t);\r
+\r
+                       if (ret != ERR_NO_ERROR)\r
+                       {\r
+                               // エラー発生\r
+                               CmdPrintError(c, ret);\r
+                               FreeParamValueList(o);\r
+                               return ret;\r
+                       }\r
+               }\r
+       }\r
+\r
+       FreeRpcAdminOption(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB 拡張オプションの一覧の取得\r
+UINT PsExtOptionList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ADMIN_OPTION t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetHubExtOptions(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               CT *ct = CtNewStandardEx();\r
+               UINT i;\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       ADMIN_OPTION *e = &t.Items[i];\r
+                       wchar_t tmp1[MAX_SIZE];\r
+                       wchar_t tmp2[MAX_SIZE];\r
+\r
+                       StrToUni(tmp1, sizeof(tmp1), e->Name);\r
+                       UniToStru(tmp2, e->Value);\r
+\r
+                       CtInsert(ct, tmp1, tmp2, GetHubAdminOptionHelpString(e->Name));\r
+\r
+               }\r
+\r
+               CtFreeEx(ct, c, true);\r
+       }\r
+\r
+       FreeRpcAdminOption(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想 HUB 拡張オプションの値の設定\r
+UINT PsExtOptionSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ADMIN_OPTION t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[name]", CmdPrompt, _UU("CMD_AdminOptionSet_Prompt_name"), CmdEvalNotEmpty, NULL},\r
+               {"VALUE", CmdPrompt, _UU("CMD_AdminOptionSet_Prompt_VALUE"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetHubExtOptions(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               UINT i;\r
+               bool b = false;\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       if (StrCmpi(t.Items[i].Name, GetParamStr(o, "[name]")) == 0)\r
+                       {\r
+                               t.Items[i].Value = GetParamInt(o, "VALUE");\r
+                               b = true;\r
+                       }\r
+               }\r
+\r
+               if (b == false)\r
+               {\r
+                       // エラー発生\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       FreeRpcAdminOption(&t);\r
+                       return ret;\r
+               }\r
+               else\r
+               {\r
+                       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+                       ret = ScSetHubExtOptions(ps->Rpc, &t);\r
+\r
+                       if (ret != ERR_NO_ERROR)\r
+                       {\r
+                               // エラー発生\r
+                               CmdPrintError(c, ret);\r
+                               FreeParamValueList(o);\r
+                               return ret;\r
+                       }\r
+               }\r
+       }\r
+\r
+       FreeRpcAdminOption(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 無効な証明書リストの一覧の取得\r
+UINT PsCrlList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_CRL t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumCrl(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               UINT i;\r
+               CT *ct = CtNew();\r
+\r
+               CtInsertColumn(ct, _UU("CMD_ID"), false);\r
+               CtInsertColumn(ct, _UU("SM_CRL_COLUMN_1"), false);\r
+\r
+               for (i = 0;i < t.NumItem;i++)\r
+               {\r
+                       wchar_t tmp[64];\r
+                       RPC_ENUM_CRL_ITEM *e = &t.Items[i];\r
+\r
+                       UniToStru(tmp, e->Key);\r
+                       CtInsert(ct, tmp, e->CrlInfo);\r
+               }\r
+\r
+               CtFreeEx(ct, c, true);\r
+       }\r
+\r
+       FreeRpcEnumCrl(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 無効な証明書の追加\r
+UINT PsCrlAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CRL t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               {"SERIAL", NULL, NULL, NULL, NULL},\r
+               {"MD5", NULL, NULL, NULL, NULL},\r
+               {"SHA1", NULL, NULL, NULL, NULL},\r
+               {"CN", NULL, NULL, NULL, NULL},\r
+               {"O", NULL, NULL, NULL, NULL},\r
+               {"OU", NULL, NULL, NULL, NULL},\r
+               {"C", NULL, NULL, NULL, NULL},\r
+               {"ST", NULL, NULL, NULL, NULL},\r
+               {"L", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       {\r
+               bool param_exists = false;\r
+               CRL *crl = ZeroMalloc(sizeof(CRL));\r
+               NAME *n;\r
+               n = crl->Name = ZeroMalloc(sizeof(NAME));\r
+\r
+               if (IsEmptyStr(GetParamStr(o, "CN")) == false)\r
+               {\r
+                       n->CommonName = CopyUniStr(GetParamUniStr(o, "CN"));\r
+                       param_exists = true;\r
+               }\r
+\r
+               if (IsEmptyStr(GetParamStr(o, "O")) == false)\r
+               {\r
+                       n->CommonName = CopyUniStr(GetParamUniStr(o, "O"));\r
+                       param_exists = true;\r
+               }\r
+\r
+               if (IsEmptyStr(GetParamStr(o, "OU")) == false)\r
+               {\r
+                       n->CommonName = CopyUniStr(GetParamUniStr(o, "OU"));\r
+                       param_exists = true;\r
+               }\r
+\r
+               if (IsEmptyStr(GetParamStr(o, "C")) == false)\r
+               {\r
+                       n->CommonName = CopyUniStr(GetParamUniStr(o, "C"));\r
+                       param_exists = true;\r
+               }\r
+\r
+               if (IsEmptyStr(GetParamStr(o, "ST")) == false)\r
+               {\r
+                       n->CommonName = CopyUniStr(GetParamUniStr(o, "ST"));\r
+                       param_exists = true;\r
+               }\r
+\r
+               if (IsEmptyStr(GetParamStr(o, "L")) == false)\r
+               {\r
+                       n->CommonName = CopyUniStr(GetParamUniStr(o, "L"));\r
+                       param_exists = true;\r
+               }\r
+\r
+               if (IsEmptyStr(GetParamStr(o, "SERIAL")) == false)\r
+               {\r
+                       BUF *b;\r
+\r
+                       b = StrToBin(GetParamStr(o, "SERIAL"));\r
+\r
+                       if (b != NULL && b->Size >= 1)\r
+                       {\r
+                               crl->Serial = NewXSerial(b->Buf, b->Size);\r
+                               param_exists = true;\r
+                       }\r
+\r
+                       FreeBuf(b);\r
+               }\r
+\r
+               if (IsEmptyStr(GetParamStr(o, "MD5")) == false)\r
+               {\r
+                       BUF *b;\r
+\r
+                       b = StrToBin(GetParamStr(o, "MD5"));\r
+\r
+                       if (b != NULL && b->Size == MD5_SIZE)\r
+                       {\r
+                               Copy(crl->DigestMD5, b->Buf, MD5_SIZE);\r
+                               param_exists = true;\r
+                       }\r
+\r
+                       FreeBuf(b);\r
+               }\r
+\r
+               if (IsEmptyStr(GetParamStr(o, "SHA1")) == false)\r
+               {\r
+                       BUF *b;\r
+\r
+                       b = StrToBin(GetParamStr(o, "SHA1"));\r
+\r
+                       if (b != NULL && b->Size == SHA1_SIZE)\r
+                       {\r
+                               Copy(crl->DigestSHA1, b->Buf, SHA1_SIZE);\r
+                               param_exists = true;\r
+                       }\r
+\r
+                       FreeBuf(b);\r
+               }\r
+\r
+               t.Crl = crl;\r
+\r
+               if (param_exists == false)\r
+               {\r
+                       FreeRpcCrl(&t);\r
+                       ret = ERR_INVALID_PARAMETER;\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+       }\r
+\r
+       // RPC 呼び出し\r
+       ret = ScAddCrl(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcCrl(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 無効な証明書の削除\r
+UINT PsCrlDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CRL t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[id]", CmdPrompt, _UU("CMD_CrlDel_Prompt_ID"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.Key = GetParamInt(o, "[id]");\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDelCrl(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeRpcCrl(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 無効な証明書の取得\r
+UINT PsCrlGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_CRL t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[id]", CmdPrompt, _UU("CMD_CrlGet_Prompt_ID"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+       t.Key = GetParamInt(o, "[id]");\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetCrl(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // 内容の表示\r
+               CT *ct = CtNewStandard();\r
+               CRL *crl = t.Crl;\r
+               NAME *n;\r
+\r
+               if (crl != NULL)\r
+               {\r
+                       n = crl->Name;\r
+\r
+                       if (n != NULL)\r
+                       {\r
+                               if (UniIsEmptyStr(n->CommonName) == false)\r
+                               {\r
+                                       CtInsert(ct, _UU("CMD_CrlGet_CN"), n->CommonName);\r
+                               }\r
+                               if (UniIsEmptyStr(n->Organization) == false)\r
+                               {\r
+                                       CtInsert(ct, _UU("CMD_CrlGet_O"), n->Organization);\r
+                               }\r
+                               if (UniIsEmptyStr(n->Unit) == false)\r
+                               {\r
+                                       CtInsert(ct, _UU("CMD_CrlGet_OU"), n->Unit);\r
+                               }\r
+                               if (UniIsEmptyStr(n->Country) == false)\r
+                               {\r
+                                       CtInsert(ct, _UU("CMD_CrlGet_C"), n->Country);\r
+                               }\r
+                               if (UniIsEmptyStr(n->State) == false)\r
+                               {\r
+                                       CtInsert(ct, _UU("CMD_CrlGet_ST"), n->State);\r
+                               }\r
+                               if (UniIsEmptyStr(n->Local) == false)\r
+                               {\r
+                                       CtInsert(ct, _UU("CMD_CrlGet_L"), n->Local);\r
+                               }\r
+                       }\r
+\r
+                       if (crl->Serial != NULL && crl->Serial->size >= 1)\r
+                       {\r
+                               wchar_t tmp[MAX_SIZE];\r
+                               char str[MAX_SIZE];\r
+\r
+                               BinToStrEx(str, sizeof(str), crl->Serial->data, crl->Serial->size);\r
+                               StrToUni(tmp, sizeof(tmp), str);\r
+\r
+                               CtInsert(ct, _UU("CMD_CrlGet_SERI"), tmp);\r
+                       }\r
+\r
+                       if (IsZero(crl->DigestMD5, MD5_SIZE) == false)\r
+                       {\r
+                               wchar_t tmp[MAX_SIZE];\r
+                               char str[MAX_SIZE];\r
+\r
+                               BinToStrEx(str, sizeof(str), crl->DigestMD5, MD5_SIZE);\r
+                               StrToUni(tmp, sizeof(tmp), str);\r
+\r
+                               CtInsert(ct, _UU("CMD_CrlGet_MD5_HASH"), tmp);\r
+                       }\r
+\r
+                       if (IsZero(crl->DigestSHA1, SHA1_SIZE) == false)\r
+                       {\r
+                               wchar_t tmp[MAX_SIZE];\r
+                               char str[MAX_SIZE];\r
+\r
+                               BinToStrEx(str, sizeof(str), crl->DigestSHA1, SHA1_SIZE);\r
+                               StrToUni(tmp, sizeof(tmp), str);\r
+\r
+                               CtInsert(ct, _UU("CMD_CrlGet_SHA1_HASH"), tmp);\r
+                       }\r
+               }\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeRpcCrl(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// IP アクセス制御リストのルール一覧の取得\r
+UINT PsAcList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_AC_LIST t;\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetAcList(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               UINT i;\r
+               CT *ct;\r
+\r
+               ct = CtNew();\r
+               CtInsertColumn(ct, _UU("SM_AC_COLUMN_1"), true);\r
+               CtInsertColumn(ct, _UU("SM_AC_COLUMN_2"), true);\r
+               CtInsertColumn(ct, _UU("SM_AC_COLUMN_3"), false);\r
+               CtInsertColumn(ct, _UU("SM_AC_COLUMN_4"), false);\r
+\r
+               for (i = 0;i < LIST_NUM(t.o);i++)\r
+               {\r
+                       wchar_t tmp1[32], *tmp2, tmp3[MAX_SIZE], tmp4[32];\r
+                       char *tmp_str;\r
+                       AC *ac = LIST_DATA(t.o, i);\r
+\r
+                       UniToStru(tmp1, ac->Id);\r
+                       tmp2 = ac->Deny ? _UU("SM_AC_DENY") : _UU("SM_AC_PASS");\r
+                       tmp_str = GenerateAcStr(ac);\r
+                       StrToUni(tmp3, sizeof(tmp3), tmp_str);\r
+\r
+                       Free(tmp_str);\r
+\r
+                       UniToStru(tmp4, ac->Priority);\r
+\r
+                       CtInsert(ct, tmp1, tmp4, tmp2, tmp3);\r
+               }\r
+\r
+               CtFree(ct, c);\r
+       }\r
+\r
+       FreeRpcAcList(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// IP アクセス制御リストにルールを追加 (IPv4)\r
+UINT PsAcAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_AC_LIST t;\r
+       // 指定できるパラメータ リスト\r
+       CMD_EVAL_MIN_MAX mm =\r
+       {\r
+               "CMD_AcAdd_Eval_PRIORITY", 1, 4294967295UL,\r
+       };\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[allow|deny]", CmdPrompt, _UU("CMD_AcAdd_Prompt_AD"), CmdEvalNotEmpty, NULL},\r
+               {"PRIORITY", CmdPrompt, _UU("CMD_AcAdd_Prompt_PRIORITY"), CmdEvalMinMax, &mm},\r
+               {"IP", CmdPrompt, _UU("CMD_AcAdd_Prompt_IP"), CmdEvalIpAndMask4, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetAcList(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // リストに新しい項目を追加する\r
+               AC *ac = ZeroMalloc(sizeof(AC));\r
+               char *test = GetParamStr(o, "[allow|deny]");\r
+               UINT u_ip, u_mask;\r
+\r
+               if (StartWith("deny", test))\r
+               {\r
+                       ac->Deny = true;\r
+               }\r
+\r
+               ParseIpAndMask4(GetParamStr(o, "IP"), &u_ip, &u_mask);\r
+               UINTToIP(&ac->IpAddress, u_ip);\r
+\r
+               if (u_mask == 0xffffffff)\r
+               {\r
+                       ac->Masked = false;\r
+               }\r
+               else\r
+               {\r
+                       ac->Masked = true;\r
+                       UINTToIP(&ac->SubnetMask, u_mask);\r
+               }\r
+\r
+               ac->Priority = GetParamInt(o, "PRIORITY");\r
+\r
+               Insert(t.o, ac);\r
+\r
+               ret = ScSetAcList(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+       }\r
+\r
+       FreeRpcAcList(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// IP アクセス制御リストにルールを追加 (IPv6)\r
+UINT PsAcAdd6(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_AC_LIST t;\r
+       // 指定できるパラメータ リスト\r
+       CMD_EVAL_MIN_MAX mm =\r
+       {\r
+               "CMD_AcAdd6_Eval_PRIORITY", 1, 4294967295UL,\r
+       };\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[allow|deny]", CmdPrompt, _UU("CMD_AcAdd6_Prompt_AD"), CmdEvalNotEmpty, NULL},\r
+               {"PRIORITY", CmdPrompt, _UU("CMD_AcAdd6_Prompt_PRIORITY"), CmdEvalMinMax, &mm},\r
+               {"IP", CmdPrompt, _UU("CMD_AcAdd6_Prompt_IP"), CmdEvalIpAndMask6, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetAcList(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // リストに新しい項目を追加する\r
+               AC *ac = ZeroMalloc(sizeof(AC));\r
+               char *test = GetParamStr(o, "[allow|deny]");\r
+               IP u_ip, u_mask;\r
+\r
+               if (StartWith("deny", test))\r
+               {\r
+                       ac->Deny = true;\r
+               }\r
+\r
+               ParseIpAndMask6(GetParamStr(o, "IP"), &u_ip, &u_mask);\r
+               Copy(&ac->IpAddress, &u_ip, sizeof(IP));\r
+\r
+               if (SubnetMaskToInt6(&u_mask) == 128)\r
+               {\r
+                       ac->Masked = false;\r
+               }\r
+               else\r
+               {\r
+                       ac->Masked = true;\r
+                       Copy(&ac->SubnetMask, &u_mask, sizeof(IP));\r
+               }\r
+\r
+               ac->Priority = GetParamInt(o, "PRIORITY");\r
+\r
+               Insert(t.o, ac);\r
+\r
+               ret = ScSetAcList(ps->Rpc, &t);\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+       }\r
+\r
+       FreeRpcAcList(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// デバッグコマンドを実行する\r
+UINT PsDebug(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       UINT id;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[id]", NULL, NULL, NULL, NULL},\r
+               {"ARG", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       id = GetParamInt(o, "[id]");\r
+\r
+       if (true)\r
+       {\r
+               RPC_TEST t;\r
+               UINT ret;\r
+\r
+               c->Write(c, _UU("CMD_Debug_Msg1"));\r
+\r
+               Zero(&t, sizeof(t));\r
+\r
+               t.IntValue = id;\r
+               StrCpy(t.StrValue, sizeof(t.StrValue), GetParamStr(o, "ARG"));\r
+\r
+               ret = ScDebug(ps->Rpc, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+               else\r
+               {\r
+                       wchar_t tmp[sizeof(t.StrValue)];\r
+\r
+                       UniFormat(tmp, sizeof(tmp), _UU("CMD_Debug_Msg2"), t.StrValue);\r
+                       c->Write(c, tmp);\r
+               }\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// サーバーの設定ファイルをフラッシュする\r
+UINT PsFlush(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       if (true)\r
+       {\r
+               RPC_TEST t;\r
+               UINT ret;\r
+               wchar_t tmp[MAX_SIZE];\r
+               char sizestr[MAX_SIZE];\r
+\r
+               c->Write(c, _UU("CMD_Flush_Msg1"));\r
+\r
+               Zero(&t, sizeof(t));\r
+\r
+               ret = ScFlush(ps->Rpc, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+\r
+               ToStr3(sizestr, sizeof(sizestr), (UINT64)t.IntValue);\r
+               UniFormat(tmp, sizeof(tmp), _UU("CMD_Flush_Msg2"), sizestr);\r
+               c->Write(c, tmp);\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// クラッシュさせる\r
+UINT PsCrash(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       char *yes;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[yes]", CmdPrompt, _UU("CMD_Crash_Confirm"), NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       yes = GetParamStr(o, "[yes]");\r
+\r
+       if (StrCmpi(yes, "yes") != 0)\r
+       {\r
+               c->Write(c, _UU("CMD_Crash_Aborted"));\r
+       }\r
+       else\r
+       {\r
+               RPC_TEST t;\r
+               UINT ret;\r
+\r
+               c->Write(c, _UU("CMD_Crash_Msg"));\r
+\r
+               Zero(&t, sizeof(t));\r
+\r
+               ret = ScCrash(ps->Rpc, &t);\r
+\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// IP アクセス制御リスト内のルールの削除\r
+UINT PsAcDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_AC_LIST t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[id]", CmdPrompt, _UU("CMD_AcDel_Prompt_ID"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       // 仮想 HUB が選択されていない場合はエラー\r
+       if (ps->HubName == NULL)\r
+       {\r
+               c->Write(c, _UU("CMD_Hub_Not_Selected"));\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetAcList(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+       else\r
+       {\r
+               // ID 一致を削除\r
+               UINT i;\r
+               bool b = false;\r
+\r
+               for (i = 0;i < LIST_NUM(t.o);i++)\r
+               {\r
+                       AC *ac = LIST_DATA(t.o, i);\r
+\r
+                       if (ac->Id == GetParamInt(o, "[id]"))\r
+                       {\r
+                               Delete(t.o, ac);\r
+                               Free(ac);\r
+                               b = true;\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               if (b == false)\r
+               {\r
+                       ret = ERR_OBJECT_NOT_FOUND;\r
+                       FreeRpcAcList(&t);\r
+               }\r
+               else\r
+               {\r
+                       ret = ScSetAcList(ps->Rpc, &t);\r
+               }\r
+               if (ret != ERR_NO_ERROR)\r
+               {\r
+                       // エラー発生\r
+                       CmdPrintError(c, ret);\r
+                       FreeParamValueList(o);\r
+                       return ret;\r
+               }\r
+       }\r
+\r
+       FreeRpcAcList(&t);\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 新しいライセンスキーの登録\r
+UINT PsLicenseAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_TEST t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[key]", CmdPrompt, _UU("CMD_LicenseAdd_Prompt_Key"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       StrCpy(t.StrValue, sizeof(t.StrValue), GetParamStr(o, "[key]"));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScAddLicenseKey(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 登録されているライセンスの削除\r
+UINT PsLicenseDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_TEST t;\r
+       // 指定できるパラメータ リスト\r
+       PARAM args[] =\r
+       {\r
+               // "name", prompt_proc, prompt_param, eval_proc, eval_param\r
+               {"[id]", CmdPrompt, _UU("CMD_LicenseDel_Prompt_ID"), CmdEvalNotEmpty, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.IntValue = GetParamInt(o, "[id]");\r
+\r
+       // RPC 呼び出し\r
+       ret = ScDelLicenseKey(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 登録されているライセンス一覧の取得\r
+UINT PsLicenseList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_ENUM_LICENSE_KEY t;\r
+       CT *ct;\r
+       UINT i;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScEnumLicenseKey(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       ct = CtNew();\r
+       CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_1"), false);\r
+       CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_2"), false);\r
+       CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_3"), false);\r
+       CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_4"), false);\r
+       CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_5"), false);\r
+       CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_6"), false);\r
+       CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_7"), false);\r
+       CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_8"), false);\r
+       CtInsertColumn(ct, _UU("SM_LICENSE_COLUMN_9"), false);\r
+\r
+       for (i = 0;i < t.NumItem;i++)\r
+       {\r
+               wchar_t tmp1[32], tmp2[LICENSE_KEYSTR_LEN + 1], tmp3[LICENSE_MAX_PRODUCT_NAME_LEN + 1],\r
+                       *tmp4, tmp5[128], tmp6[LICENSE_LICENSEID_STR_LEN + 1], tmp7[64],\r
+                       tmp8[64], tmp9[64];\r
+               RPC_ENUM_LICENSE_KEY_ITEM *e = &t.Items[i];\r
+\r
+               UniToStru(tmp1, e->Id);\r
+               StrToUni(tmp2, sizeof(tmp2), e->LicenseKey);\r
+               StrToUni(tmp3, sizeof(tmp3), e->LicenseName);\r
+               tmp4 = LiGetLicenseStatusStr(e->Status);\r
+               if (e->Expires == 0)\r
+               {\r
+                       UniStrCpy(tmp5, sizeof(tmp5), _UU("SM_LICENSE_NO_EXPIRES"));\r
+               }\r
+               else\r
+               {\r
+                       GetDateStrEx64(tmp5, sizeof(tmp5), e->Expires, NULL);\r
+               }\r
+               StrToUni(tmp6, sizeof(tmp6), e->LicenseId);\r
+               UniToStru(tmp7, e->ProductId);\r
+               UniFormat(tmp8, sizeof(tmp8), L"%I64u", e->SystemId);\r
+               UniToStru(tmp9, e->SerialId);\r
+\r
+               CtInsert(ct,\r
+                       tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9);\r
+       }\r
+\r
+       CtFreeEx(ct, c, true);\r
+\r
+       FreeRpcEnumLicenseKey(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 現在の VPN Server のライセンス状態の取得\r
+UINT PsLicenseStatus(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret = 0;\r
+       RPC_LICENSE_STATUS st;\r
+       CT *ct;\r
+       wchar_t tmp[MAX_SIZE];\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&st, sizeof(st));\r
+\r
+       // RPC 呼び出し\r
+       ret = ScGetLicenseStatus(ps->Rpc, &st);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               // エラー発生\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       ct = CtNewStandard();\r
+\r
+       if (st.EditionId == LICENSE_EDITION_VPN3_NO_LICENSE)\r
+       {\r
+               CtInsert(ct, _UU("SM_NO_LICENSE_COLUMN"), _UU("SM_NO_LICENSE"));\r
+       }\r
+       else\r
+       {\r
+               // 製品エディション名\r
+               StrToUni(tmp, sizeof(tmp), st.EditionStr);\r
+               CtInsert(ct, _UU("SM_LICENSE_STATUS_EDITION"), tmp);\r
+\r
+               // リリース日付\r
+               if (st.ReleaseDate != 0)\r
+               {\r
+                       GetDateStrEx64(tmp, sizeof(tmp), st.ReleaseDate, NULL);\r
+                       CtInsert(ct, _UU("SM_LICENSE_STATUS_RELEASE"), tmp);\r
+               }\r
+\r
+               // 現在のシステム ID\r
+               UniFormat(tmp, sizeof(tmp), L"%I64u", st.SystemId);\r
+               CtInsert(ct, _UU("SM_LICENSE_STATUS_SYSTEM_ID"), tmp);\r
+\r
+               // 現在の製品ライセンスの有効期限\r
+               if (st.SystemExpires == 0)\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_NO_EXPIRES"));\r
+               }\r
+               else\r
+               {\r
+                       GetDateStrEx64(tmp, sizeof(tmp), st.SystemExpires, NULL);\r
+               }\r
+               CtInsert(ct,  _UU("SM_LICENSE_STATUS_EXPIRES"), tmp);\r
+\r
+               // サブスクリプション (サポート) 契約\r
+               if (st.NeedSubscription == false)\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_STATUS_SUBSCRIPTION_NONEED"));\r
+               }\r
+               else\r
+               {\r
+                       if (st.SubscriptionExpires == 0)\r
+                       {\r
+                               UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_STATUS_SUBSCRIPTION_NONE"));\r
+                       }\r
+                       else\r
+                       {\r
+                               wchar_t dtstr[MAX_PATH];\r
+\r
+                               GetDateStrEx64(dtstr, sizeof(dtstr), st.SubscriptionExpires, NULL);\r
+\r
+                               UniFormat(tmp, sizeof(tmp),\r
+                                       st.IsSubscriptionExpired ? _UU("SM_LICENSE_STATUS_SUBSCRIPTION_EXPIRED") :  _UU("SM_LICENSE_STATUS_SUBSCRIPTION_VALID"),\r
+                                       dtstr);\r
+                       }\r
+               }\r
+               CtInsert(ct, _UU("SM_LICENSE_STATUS_SUBSCRIPTION"), tmp);\r
+\r
+               if (st.NeedSubscription == false && st.SubscriptionExpires != 0)\r
+               {\r
+                       wchar_t dtstr[MAX_PATH];\r
+\r
+                       GetDateStrEx64(dtstr, sizeof(dtstr), st.SubscriptionExpires, NULL);\r
+\r
+                       CtInsert(ct, _UU("SM_LICENSE_STATUS_SUBSCRIPTION_BUILD_STR"), tmp);\r
+               }\r
+\r
+               if (GetCapsBool(ps->CapsList, "b_vpn3"))\r
+               {\r
+                       // ユーザー作成可能数\r
+                       if (st.NumClientConnectLicense == INFINITE)\r
+                       {\r
+                               UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_INFINITE"));\r
+                       }\r
+                       else\r
+                       {\r
+                               UniToStru(tmp, st.NumClientConnectLicense);\r
+                       }\r
+                       CtInsert(ct, _UU("SM_LICENSE_NUM_CLIENT"), tmp);\r
+               }\r
+\r
+               // クライアント同時接続可能数\r
+               if (st.NumBridgeConnectLicense == INFINITE)\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("SM_LICENSE_INFINITE"));\r
+               }\r
+               else\r
+               {\r
+                       UniToStru(tmp, st.NumBridgeConnectLicense);\r
+               }\r
+               CtInsert(ct, _UU("SM_LICENSE_NUM_BRIDGE"), tmp);\r
+\r
+               // エンタープライズ機能の利用可否\r
+               CtInsert(ct, _UU("SM_LICENSE_STATUS_ENTERPRISE"),\r
+                       st.AllowEnterpriseFunction ? _UU("SM_LICENSE_STATUS_ENTERPRISE_YES") : _UU("SM_LICENSE_STATUS_ENTERPRISE_NO"));\r
+       }\r
+\r
+       CtFreeEx(ct, c, false);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+\r
+// クラスタ設定の取得\r
+UINT PsClusterSettingGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret;\r
+       RPC_FARM t;\r
+       CT *ct;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       ret = ScGetFarmSetting(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       if (t.Weight == 0)\r
+       {\r
+               t.Weight = FARM_DEFAULT_WEIGHT;\r
+       }\r
+\r
+       // クラスタ設定の表示\r
+       ct = CtNewStandard();\r
+\r
+       CtInsert(ct, _UU("CMD_ClusterSettingGet_Current"),\r
+               GetServerTypeStr(t.ServerType));\r
+\r
+       if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               CtInsert(ct, _UU("CMD_ClusterSettingGet_ControllerOnly"), t.ControllerOnly ? _UU("SEC_YES") : _UU("SEC_NO"));\r
+       }\r
+\r
+       if (t.ServerType != SERVER_TYPE_STANDALONE)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+\r
+               UniToStru(tmp, t.Weight);\r
+\r
+               CtInsert(ct, _UU("CMD_ClusterSettingGet_Weight"), tmp);\r
+       }\r
+\r
+       if (t.ServerType == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               wchar_t tmp[MAX_SIZE];\r
+               UINT i;\r
+\r
+               // 公開 IP アドレス\r
+               if (t.PublicIp != 0)\r
+               {\r
+                       IPToUniStr32(tmp, sizeof(tmp), t.PublicIp);\r
+               }\r
+               else\r
+               {\r
+                       UniStrCpy(tmp, sizeof(tmp), _UU("CMD_ClusterSettingGet_None"));\r
+               }\r
+\r
+               CtInsert(ct, _UU("CMD_ClusterSettingGet_PublicIp"), tmp);\r
+\r
+               // 公開ポート一覧\r
+               tmp[0] = 0;\r
+               for (i = 0;i < t.NumPort;i++)\r
+               {\r
+                       wchar_t tmp2[64];\r
+\r
+                       UniFormat(tmp2, sizeof(tmp2), L"%u, ", t.Ports[i]);\r
+\r
+                       UniStrCat(tmp, sizeof(tmp), tmp2);\r
+               }\r
+\r
+               if (UniEndWith(tmp, L", "))\r
+               {\r
+                       tmp[UniStrLen(tmp) - 2] = 0;\r
+               }\r
+\r
+               CtInsert(ct, _UU("CMD_ClusterSettingGet_PublicPorts"), tmp);\r
+\r
+               // 接続先コントローラ\r
+               UniFormat(tmp, sizeof(tmp), L"%S:%u", t.ControllerName, t.ControllerPort);\r
+               CtInsert(ct, _UU("CMD_ClusterSettingGet_Controller"), tmp);\r
+       }\r
+\r
+       CtFree(ct, c);\r
+\r
+       FreeRpcFarm(&t);\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// サーバーパスワードの設定\r
+UINT PsServerPasswordSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret;\r
+       RPC_SET_PASSWORD t;\r
+       char *pw;\r
+       PARAM args[] =\r
+       {\r
+               {"[password]", CmdPromptChoosePassword, NULL, NULL, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       pw = GetParamStr(o, "[password]");\r
+\r
+       Zero(&t, sizeof(t));\r
+       Hash(t.HashedPassword, pw, StrLen(pw), true);\r
+\r
+       ret = ScSetServerPassword(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// パスワード決定プロンプト (プロンプト関数用)\r
+wchar_t *CmdPromptChoosePassword(CONSOLE *c, void *param)\r
+{\r
+       char *s;\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       s = CmdPasswordPrompt(c);\r
+\r
+       if (s == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+       else\r
+       {\r
+               wchar_t *ret = CopyStrToUni(s);\r
+\r
+               Free(s);\r
+\r
+               return ret;\r
+       }\r
+}\r
+\r
+// パスワード入力用プロンプト (汎用)\r
+char *CmdPasswordPrompt(CONSOLE *c)\r
+{\r
+       char *pw1, *pw2;\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       c->Write(c, _UU("CMD_UTVPNCMD_PWPROMPT_0"));\r
+\r
+RETRY:\r
+       c->Write(c, L"");\r
+\r
+\r
+       pw1 = c->ReadPassword(c, _UU("CMD_UTVPNCMD_PWPROMPT_1"));\r
+       if (pw1 == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       pw2 = c->ReadPassword(c, _UU("CMD_UTVPNCMD_PWPROMPT_2"));\r
+       if (pw2 == NULL)\r
+       {\r
+               Free(pw1);\r
+               return NULL;\r
+       }\r
+\r
+       c->Write(c, L"");\r
+\r
+       if (StrCmp(pw1, pw2) != 0)\r
+       {\r
+               Free(pw1);\r
+               Free(pw2);\r
+               c->Write(c, _UU("CMD_UTVPNCMD_PWPROMPT_3"));\r
+               goto RETRY;\r
+       }\r
+\r
+       Free(pw1);\r
+\r
+       return pw2;\r
+}\r
+\r
+// リスナー無効化\r
+UINT PsListenerDisable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret;\r
+       RPC_LISTENER t;\r
+       PARAM args[] =\r
+       {\r
+               {"[port]", CmdPromptPort, _UU("CMD_ListenerDisable_PortPrompt"), CmdEvalPort, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.Enable = false;\r
+       t.Port = ToInt(GetParamStr(o, "[port]"));\r
+\r
+       ret = ScEnableListener(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// リスナー有効化\r
+UINT PsListenerEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret;\r
+       RPC_LISTENER t;\r
+       PARAM args[] =\r
+       {\r
+               {"[port]", CmdPromptPort, _UU("CMD_ListenerEnable_PortPrompt"), CmdEvalPort, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.Enable = true;\r
+       t.Port = ToInt(GetParamStr(o, "[port]"));\r
+\r
+       ret = ScEnableListener(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// コンソールテーブルの 1 行を描画\r
+void CtPrintRow(CONSOLE *c, UINT num, UINT *widths, wchar_t **strings, bool *rights, char separate_char)\r
+{\r
+       UINT i;\r
+       wchar_t *buf;\r
+       UINT buf_size;\r
+       bool is_sep_line = true;\r
+       // 引数チェック\r
+       if (c == NULL || num == 0 || widths == NULL || strings == NULL || rights == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       buf_size = 32;\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               buf_size += sizeof(wchar_t) * widths[i] + 6;\r
+       }\r
+\r
+       buf = ZeroMalloc(buf_size);\r
+\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               char *tmp;\r
+               wchar_t *space_string;\r
+               UINT w;\r
+               UINT space = 0;\r
+               wchar_t *string = strings[i];\r
+               wchar_t *tmp_line = NULL;\r
+\r
+               if (UniStrCmpi(string, L"---") == 0)\r
+               {\r
+                       char *s = MakeCharArray('-', widths[i]);\r
+                       tmp_line = string = CopyStrToUni(s);\r
+\r
+                       Free(s);\r
+               }\r
+               else\r
+               {\r
+                       is_sep_line = false;\r
+               }\r
+\r
+               w = UniStrWidth(string);\r
+\r
+               if (widths[i] >= w)\r
+               {\r
+                       space = widths[i] - w;\r
+               }\r
+\r
+               tmp = MakeCharArray(' ', space);\r
+               space_string = CopyStrToUni(tmp);\r
+\r
+               if (rights[i] != false)\r
+               {\r
+                       UniStrCat(buf, buf_size, space_string);\r
+               }\r
+\r
+               UniStrCat(buf, buf_size, string);\r
+\r
+               if (rights[i] == false)\r
+               {\r
+                       UniStrCat(buf, buf_size, space_string);\r
+               }\r
+\r
+               Free(space_string);\r
+               Free(tmp);\r
+\r
+               if (i < (num - 1))\r
+               {\r
+                       wchar_t tmp[4];\r
+                       char str[2];\r
+\r
+                       if (UniStrCmpi(strings[i], L"---") == 0)\r
+                       {\r
+                               str[0] = '+';\r
+                       }\r
+                       else\r
+                       {\r
+                               str[0] = separate_char;\r
+                       }\r
+                       str[1] = 0;\r
+\r
+                       StrToUni(tmp, sizeof(tmp), str);\r
+\r
+                       UniStrCat(buf, buf_size, tmp);\r
+               }\r
+\r
+               if (tmp_line != NULL)\r
+               {\r
+                       Free(tmp_line);\r
+               }\r
+       }\r
+\r
+       UniTrimRight(buf);\r
+\r
+       if (is_sep_line)\r
+       {\r
+               if (UniStrLen(buf) > (c->GetWidth(c) - 1))\r
+               {\r
+                       buf[c->GetWidth(c) - 1] = 0;\r
+               }\r
+       }\r
+\r
+       c->Write(c, buf);\r
+\r
+       Free(buf);\r
+}\r
+\r
+// コンソール テーブルを標準形式で描画\r
+void CtPrintStandard(CT *ct, CONSOLE *c)\r
+{\r
+       CT *t;\r
+       UINT i, j;\r
+       // 引数チェック\r
+       if (ct == NULL || c == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       t = CtNewStandard();\r
+       for (i = 0;i < LIST_NUM(ct->Rows);i++)\r
+       {\r
+               CTR *row = LIST_DATA(ct->Rows, i);\r
+\r
+               for (j = 0;j < LIST_NUM(ct->Columns);j++)\r
+               {\r
+                       CTC *column = LIST_DATA(ct->Columns, j);\r
+\r
+                       CtInsert(t, column->String, row->Strings[j]);\r
+               }\r
+\r
+               if (i != (LIST_NUM(ct->Rows) - 1))\r
+               {\r
+                       CtInsert(t, L"---", L"---");\r
+               }\r
+       }\r
+\r
+       CtFree(t, c);\r
+}\r
+\r
+// コンソールテーブルの描画\r
+void CtPrint(CT *ct, CONSOLE *c)\r
+{\r
+       UINT *widths;\r
+       UINT num;\r
+       UINT i, j;\r
+       wchar_t **header_strings;\r
+       bool *rights;\r
+       // 引数チェック\r
+       if (ct == NULL || c == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       num = LIST_NUM(ct->Columns);\r
+       widths = ZeroMalloc(sizeof(UINT) * num);\r
+\r
+       // 各列の最大文字幅を計算する\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               CTC *ctc = LIST_DATA(ct->Columns, i);\r
+               UINT w;\r
+\r
+               w = UniStrWidth(ctc->String);\r
+               widths[i] = MAX(widths[i], w);\r
+       }\r
+       for (j = 0;j < LIST_NUM(ct->Rows);j++)\r
+       {\r
+               CTR *ctr = LIST_DATA(ct->Rows, j);\r
+\r
+               for (i = 0;i < num;i++)\r
+               {\r
+                       UINT w;\r
+\r
+                       w = UniStrWidth(ctr->Strings[i]);\r
+                       widths[i] = MAX(widths[i], w);\r
+               }\r
+       }\r
+\r
+       // ヘッダ部分を表示する\r
+       header_strings = ZeroMalloc(sizeof(wchar_t *) * num);\r
+       rights = ZeroMalloc(sizeof(bool) * num);\r
+\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               CTC *ctc = LIST_DATA(ct->Columns, i);\r
+\r
+               header_strings[i] = ctc->String;\r
+               rights[i] = ctc->Right;\r
+       }\r
+\r
+       CtPrintRow(c, num, widths, header_strings, rights, '|');\r
+\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               char *s;\r
+\r
+               s = MakeCharArray('-', widths[i]);\r
+               header_strings[i] = CopyStrToUni(s);\r
+               Free(s);\r
+       }\r
+\r
+       CtPrintRow(c, num, widths, header_strings, rights, '+');\r
+\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               Free(header_strings[i]);\r
+       }\r
+\r
+       // データ部を表示する\r
+       for (j = 0;j < LIST_NUM(ct->Rows);j++)\r
+       {\r
+               CTR *ctr = LIST_DATA(ct->Rows, j);\r
+\r
+               CtPrintRow(c, num, widths, ctr->Strings, rights, '|');\r
+       }\r
+\r
+       Free(rights);\r
+       Free(header_strings);\r
+       Free(widths);\r
+}\r
+\r
+// CSV でのメタ文字をエスケープする\r
+void CtEscapeCsv(wchar_t *dst, UINT size, wchar_t *src){\r
+       UINT i;\r
+       UINT len = UniStrLen(src);\r
+       UINT idx;\r
+       BOOL need_to_escape = false;\r
+       wchar_t tmp[2]=L"*";\r
+\r
+       // 入力値のチェック\r
+       if (src==NULL || dst==NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 入力文字中にエスケープする必要のある文字が無ければそのまま出力にコピー\r
+       len = UniStrLen(src);\r
+       for (i=0; i<len; i++)\r
+       {\r
+               tmp[0] = src[i];\r
+               if (tmp[0] == L","[0] || tmp[0] == L"\n"[0] || tmp[0] == L"\""[0])\r
+               {\r
+                       need_to_escape = true;\r
+               }\r
+       }\r
+       if (need_to_escape == false)\r
+       {\r
+               UniStrCpy(dst,size,src);\r
+               return;\r
+       }\r
+\r
+       // メタ文字(改行、コンマ、ダブルクオート)を含んでいる場合は”で囲む\r
+       UniStrCpy(dst, size, L"\"");\r
+       idx = UniStrLen(dst);\r
+       if(idx<size-1)\r
+       {\r
+               for (i=0; i<len; i++)\r
+               {\r
+                       tmp[0] = src[i];\r
+                       // ”は””に変換する(MS-Excel方式)\r
+                       if (tmp[0] == L"\""[0])\r
+                       {\r
+                               UniStrCat(dst, size, tmp);\r
+                       }\r
+                       UniStrCat(dst, size, tmp);\r
+               }\r
+       }\r
+       UniStrCat(dst, size, L"\"");\r
+       return;\r
+}\r
+\r
+// コンソールテーブルの CSV 形式の表示\r
+void CtPrintCsv(CT *ct, CONSOLE *c)\r
+{\r
+       UINT i, j;\r
+       UINT num_columns = LIST_NUM(ct->Columns);\r
+       wchar_t buf[MAX_SIZE];\r
+       wchar_t fmtbuf[MAX_SIZE];\r
+\r
+       // 見出しの行を表示\r
+       buf[0] = 0;\r
+       for(i=0; i<num_columns; i++)\r
+       {\r
+               CTC *ctc = LIST_DATA(ct->Columns, i);\r
+               CtEscapeCsv(fmtbuf, MAX_SIZE, ctc->String);\r
+               UniStrCat(buf, MAX_SIZE, fmtbuf);\r
+               if(i != num_columns-1)\r
+                       UniStrCat(buf, MAX_SIZE, L",");\r
+       }\r
+       c->Write(c, buf);\r
+\r
+       // 表の本体を表示\r
+       for(j=0; j<LIST_NUM(ct->Rows); j++)\r
+       {\r
+               CTR *ctr = LIST_DATA(ct->Rows, j);\r
+               buf[0] = 0;\r
+               for(i=0; i<num_columns; i++)\r
+               {\r
+                       CtEscapeCsv(fmtbuf, MAX_SIZE, ctr->Strings[i]);\r
+                       UniStrCat(buf, MAX_SIZE, fmtbuf);\r
+                       if(i != num_columns-1)\r
+                               UniStrCat(buf, MAX_SIZE, L",");\r
+               }\r
+               c->Write(c, buf);\r
+       }\r
+}\r
+\r
+// コンソールテーブルの削除\r
+void CtFreeEx(CT *ct, CONSOLE *c, bool standard_view)\r
+{\r
+       UINT i, num;\r
+       // 引数チェック\r
+       if (ct == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       if (c != NULL)\r
+       {\r
+               if (c->ConsoleType == CONSOLE_CSV)\r
+               {\r
+                       CtPrintCsv(ct, c);\r
+               }\r
+               else\r
+               {\r
+                       if (standard_view == false)\r
+                       {\r
+                               CtPrint(ct, c);\r
+                       }\r
+                       else\r
+                       {\r
+                               CtPrintStandard(ct, c);\r
+                       }\r
+               }\r
+       }\r
+\r
+       num = LIST_NUM(ct->Columns);\r
+\r
+       for (i = 0;i < LIST_NUM(ct->Rows);i++)\r
+       {\r
+               UINT j;\r
+               CTR *ctr = LIST_DATA(ct->Rows, i);\r
+\r
+               for (j = 0;j < num;j++)\r
+               {\r
+                       Free(ctr->Strings[j]);\r
+               }\r
+\r
+               Free(ctr->Strings);\r
+               Free(ctr);\r
+       }\r
+\r
+       for (i = 0;i < LIST_NUM(ct->Columns);i++)\r
+       {\r
+               CTC *ctc = LIST_DATA(ct->Columns, i);\r
+\r
+               Free(ctc->String);\r
+               Free(ctc);\r
+       }\r
+\r
+       ReleaseList(ct->Columns);\r
+       ReleaseList(ct->Rows);\r
+\r
+       Free(ct);\r
+}\r
+void CtFree(CT *ct, CONSOLE *c)\r
+{\r
+       CtFreeEx(ct, c, false);\r
+}\r
+\r
+// テーブルに行を追加\r
+void CtInsert(CT *ct, ...)\r
+{\r
+       CTR *ctr;\r
+       UINT num, i;\r
+       va_list va;\r
+       // 引数チェック\r
+       if (ct == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       num = LIST_NUM(ct->Columns);\r
+\r
+       va_start(va, ct);\r
+\r
+       ctr = ZeroMalloc(sizeof(CTR));\r
+       ctr->Strings = ZeroMalloc(sizeof(wchar_t *) * num);\r
+\r
+       for (i = 0;i < num;i++)\r
+       {\r
+               wchar_t *s = va_arg(va, wchar_t *);\r
+\r
+               ctr->Strings[i] = CopyUniStr(s);\r
+       }\r
+\r
+       va_end(va);\r
+\r
+       Insert(ct->Rows, ctr);\r
+}\r
+\r
+// テーブルにカラムを追加\r
+void CtInsertColumn(CT *ct, wchar_t *str, bool right)\r
+{\r
+       CTC *ctc;\r
+       // 引数チェック\r
+       if (ct == NULL)\r
+       {\r
+               return;\r
+       }\r
+       if (str == NULL)\r
+       {\r
+               str = L"";\r
+       }\r
+\r
+       ctc = ZeroMalloc(sizeof(CTC));\r
+       ctc->String = CopyUniStr(str);\r
+       ctc->Right = right;\r
+\r
+       Insert(ct->Columns, ctc);\r
+}\r
+\r
+// 新規コンソールテーブルの作成\r
+CT *CtNew()\r
+{\r
+       CT *ct;\r
+\r
+       ct = ZeroMalloc(sizeof(CT));\r
+       ct->Columns = NewList(NULL);\r
+       ct->Rows = NewList(NULL);\r
+\r
+       return ct;\r
+}\r
+\r
+// テーブルのカラムに標準的なカラムを追加する\r
+CT *CtNewStandard()\r
+{\r
+       CT *ct = CtNew();\r
+\r
+       CtInsertColumn(ct, _UU("CMD_CT_STD_COLUMN_1"), false);\r
+       CtInsertColumn(ct, _UU("CMD_CT_STD_COLUMN_2"), false);\r
+\r
+       return ct;\r
+}\r
+CT *CtNewStandardEx()\r
+{\r
+       CT *ct = CtNew();\r
+\r
+       CtInsertColumn(ct, _UU("CMD_CT_STD_COLUMN_1"), false);\r
+       CtInsertColumn(ct, _UU("CMD_CT_STD_COLUMN_2"), false);\r
+       CtInsertColumn(ct, _UU("CMD_CT_STD_COLUMN_3"), false);\r
+\r
+       return ct;\r
+}\r
+\r
+// TCP リスナー一覧の取得\r
+UINT PsListenerList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret;\r
+       RPC_LISTENER_LIST t;\r
+       UINT i;\r
+       CT *ct;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       ret = ScEnumListener(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       ct = CtNew();\r
+\r
+       CtInsertColumn(ct, _UU("CM_LISTENER_COLUMN_1"), false);\r
+       CtInsertColumn(ct, _UU("CM_LISTENER_COLUMN_2"), false);\r
+\r
+       for (i = 0;i < t.NumPort;i++)\r
+       {\r
+               wchar_t *status = _UU("CM_LISTENER_OFFLINE");\r
+               wchar_t tmp[128];\r
+\r
+               if (t.Errors[i])\r
+               {\r
+                       status = _UU("CM_LISTENER_ERROR");\r
+               }\r
+               else if (t.Enables[i])\r
+               {\r
+                       status = _UU("CM_LISTENER_ONLINE");\r
+               }\r
+\r
+               UniFormat(tmp, sizeof(tmp), _UU("CM_LISTENER_TCP_PORT"), t.Ports[i]);\r
+\r
+               CtInsert(ct, tmp, status);\r
+       }\r
+\r
+       CtFree(ct, c);\r
+\r
+       FreeRpcListenerList(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// TCP リスナーの削除\r
+UINT PsListenerDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret;\r
+       RPC_LISTENER t;\r
+       PARAM args[] =\r
+       {\r
+               {"[port]", CmdPromptPort, _UU("CMD_ListenerDelete_PortPrompt"), CmdEvalPort, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.Enable = true;\r
+       t.Port = ToInt(GetParamStr(o, "[port]"));\r
+\r
+       ret = ScDeleteListener(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 行を描画\r
+void CmdPrintRow(CONSOLE *c, wchar_t *title, wchar_t *tag, ...)\r
+{\r
+       wchar_t buf[MAX_SIZE * 2];\r
+       wchar_t buf2[MAX_SIZE * 2];\r
+       va_list args;\r
+       // 引数チェック\r
+       if (title == NULL || c == NULL || tag == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       va_start(args, tag);\r
+       UniFormatArgs(buf, sizeof(buf), tag, args);\r
+\r
+       UniFormat(buf2, sizeof(buf2), L"[%s] %s", title, buf);\r
+\r
+       va_end(args);\r
+\r
+       c->Write(c, buf2);\r
+}\r
+\r
+// ServerInfoGet コマンド\r
+UINT PsServerInfoGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret;\r
+       RPC_SERVER_INFO t;\r
+       CT *ct;\r
+       wchar_t tmp[MAX_SIZE];\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       ret = ScGetServerInfo(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       ct = CtNew();\r
+\r
+       CtInsertColumn(ct, _UU("SM_STATUS_COLUMN_1"), false);\r
+       CtInsertColumn(ct, _UU("SM_STATUS_COLUMN_2"), false);\r
+\r
+       // 製品名\r
+       StrToUni(tmp, sizeof(tmp), t.ServerProductName);\r
+       CtInsert(ct, _UU("SM_INFO_PRODUCT_NAME"), tmp);\r
+\r
+       // バージョン\r
+       StrToUni(tmp, sizeof(tmp), t.ServerVersionString);\r
+       CtInsert(ct, _UU("SM_INFO_VERSION"), tmp);\r
+\r
+       // ビルド\r
+       StrToUni(tmp, sizeof(tmp), t.ServerBuildInfoString);\r
+       CtInsert(ct, _UU("SM_INFO_BUILD"), tmp);\r
+\r
+       // ホスト名\r
+       StrToUni(tmp, sizeof(tmp), t.ServerHostName);\r
+       CtInsert(ct, _UU("SM_INFO_HOSTNAME"), tmp);\r
+\r
+       // 種類\r
+       CtInsert(ct, _UU("SM_ST_SERVER_TYPE"), GetServerTypeStr(t.ServerType));\r
+\r
+       // OS\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.OsSystemName);\r
+       CtInsert(ct, _UU("SM_OS_SYSTEM_NAME"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.OsProductName);\r
+       CtInsert(ct, _UU("SM_OS_PRODUCT_NAME"), tmp);\r
+\r
+       if (t.OsInfo.OsServicePack != 0)\r
+       {\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_OS_SP_TAG"), t.OsInfo.OsServicePack);\r
+               CtInsert(ct, _UU("SM_OS_SERVICE_PACK"), tmp);\r
+       }\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.OsVendorName);\r
+       CtInsert(ct, _UU("SM_OS_VENDER_NAME"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.OsVersion);\r
+       CtInsert(ct, _UU("SM_OS_VERSION"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.KernelName);\r
+       CtInsert(ct, _UU("SM_OS_KERNEL_NAME"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.KernelVersion);\r
+       CtInsert(ct, _UU("SM_OS_KERNEL_VERSION"), tmp);\r
+\r
+       CtFree(ct, c);\r
+\r
+       FreeRpcServerInfo(&t);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// HUB の種類の文字列を取得\r
+wchar_t *GetHubTypeStr(UINT type)\r
+{\r
+       if (type == HUB_TYPE_FARM_STATIC)\r
+       {\r
+               return _UU("SM_HUB_STATIC");\r
+       }\r
+       else if (type == HUB_TYPE_FARM_DYNAMIC)\r
+       {\r
+               return _UU("SM_HUB_DYNAMIC");\r
+       }\r
+       return _UU("SM_HUB_STANDALONE");\r
+}\r
+\r
+// サーバーの種類の文字列を取得\r
+wchar_t *GetServerTypeStr(UINT type)\r
+{\r
+       if (type == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               return _UU("SM_FARM_CONTROLLER");\r
+       }\r
+       else if (type == SERVER_TYPE_FARM_MEMBER)\r
+       {\r
+               return _UU("SM_FARM_MEMBER");\r
+       }\r
+       return _UU("SM_SERVER_STANDALONE");\r
+}\r
+\r
+// ServerStatusGet コマンド\r
+UINT PsServerStatusGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret;\r
+       RPC_SERVER_STATUS t;\r
+       wchar_t tmp[MAX_PATH];\r
+       char tmp2[MAX_PATH];\r
+       CT *ct;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       ret = ScGetServerStatus(ps->Rpc, &t);\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       ct = CtNew();\r
+\r
+       CtInsertColumn(ct, _UU("SM_STATUS_COLUMN_1"), false);\r
+       CtInsertColumn(ct, _UU("SM_STATUS_COLUMN_2"), false);\r
+\r
+       // サーバーの種類\r
+       CtInsert(ct, _UU("SM_ST_SERVER_TYPE"),\r
+               t.ServerType == SERVER_TYPE_STANDALONE ? _UU("SM_SERVER_STANDALONE") :\r
+               t.ServerType == SERVER_TYPE_FARM_MEMBER ? _UU("SM_FARM_MEMBER") : _UU("SM_FARM_CONTROLLER"));\r
+\r
+       // TCP コネクション数\r
+       UniToStru(tmp, t.NumTcpConnections);\r
+       CtInsert(ct, _UU("SM_ST_NUM_TCP"), tmp);\r
+\r
+       if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               // ローカル TCP コネクション数\r
+               UniToStru(tmp, t.NumTcpConnectionsLocal);\r
+               CtInsert(ct, _UU("SM_ST_NUM_TCP_LOCAL"), tmp);\r
+\r
+               // リモート TCP コネクション数\r
+               UniToStru(tmp, t.NumTcpConnectionsRemote);\r
+               CtInsert(ct, _UU("SM_ST_NUM_TCP_REMOTE"), tmp);\r
+       }\r
+\r
+       // 仮想 HUB 数\r
+       UniToStru(tmp, t.NumHubTotal);\r
+       CtInsert(ct, _UU("SM_ST_NUM_HUB_TOTAL"), tmp);\r
+\r
+       if (t.ServerType != SERVER_TYPE_STANDALONE)\r
+       {\r
+               // スタティック HUB 数\r
+               UniToStru(tmp, t.NumHubStatic);\r
+               CtInsert(ct, _UU("SM_ST_NUM_HUB_STATIC"), tmp);\r
+\r
+               // ダイナミック HUB 数\r
+               UniToStru(tmp, t.NumHubDynamic);\r
+               CtInsert(ct, _UU("SM_ST_NUM_HUB_DYNAMIC"), tmp);\r
+       }\r
+\r
+       // セッション数\r
+       UniToStru(tmp, t.NumSessionsTotal);\r
+       CtInsert(ct, _UU("SM_ST_NUM_SESSION_TOTAL"), tmp);\r
+\r
+       if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               // ローカルセッション数\r
+               UniToStru(tmp, t.NumSessionsLocal);\r
+               CtInsert(ct, _UU("SM_ST_NUM_SESSION_LOCAL"), tmp);\r
+\r
+               // ローカルセッション数\r
+               UniToStru(tmp, t.NumSessionsRemote);\r
+               CtInsert(ct, _UU("SM_ST_NUM_SESSION_REMOTE"), tmp);\r
+       }\r
+\r
+       // MAC テーブル数\r
+       UniToStru(tmp, t.NumMacTables);\r
+       CtInsert(ct, _UU("SM_ST_NUM_MAC_TABLE"), tmp);\r
+\r
+       // IP テーブル数\r
+       UniToStru(tmp, t.NumIpTables);\r
+       CtInsert(ct, _UU("SM_ST_NUM_IP_TABLE"), tmp);\r
+\r
+       // ユーザー数\r
+       UniToStru(tmp, t.NumUsers);\r
+       CtInsert(ct, _UU("SM_ST_NUM_USERS"), tmp);\r
+\r
+       // グループ数\r
+       UniToStru(tmp, t.NumGroups);\r
+       CtInsert(ct, _UU("SM_ST_NUM_GROUPS"), tmp);\r
+\r
+       // 割り当て済みライセンス数\r
+       UniToStru(tmp, t.AssignedClientLicenses);\r
+       CtInsert(ct, _UU("SM_ST_CLIENT_LICENSE"), tmp);\r
+\r
+       UniToStru(tmp, t.AssignedBridgeLicenses);\r
+       CtInsert(ct, _UU("SM_ST_BRIDGE_LICENSE"), tmp);\r
+\r
+       if (t.ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
+       {\r
+               UniToStru(tmp, t.AssignedClientLicensesTotal);\r
+               CtInsert(ct, _UU("SM_ST_CLIENT_LICENSE_EX"), tmp);\r
+\r
+               UniToStru(tmp, t.AssignedBridgeLicensesTotal);\r
+               CtInsert(ct, _UU("SM_ST_BRIDGE_LICENSE_EX"), tmp);\r
+       }\r
+\r
+       // トラフィック\r
+       CmdInsertTrafficInfo(ct, &t.Traffic);\r
+\r
+       // サーバー起動時刻\r
+       GetDateTimeStrEx64(tmp, sizeof(tmp), SystemToLocal64(t.StartTime), NULL);\r
+       CtInsert(ct, _UU("SM_ST_START_TIME"), tmp);\r
+\r
+       // 現在時刻\r
+       GetDateTimeStrMilli64(tmp2, sizeof(tmp2), SystemToLocal64(t.CurrentTime));\r
+       StrToUni(tmp, sizeof(tmp), tmp2);\r
+       CtInsert(ct, _UU("SM_ST_CURRENT_TIME"), tmp);\r
+\r
+       // Tick 値\r
+       UniFormat(tmp, sizeof(tmp), L"%I64u", t.CurrentTick);\r
+       CtInsert(ct, _UU("SM_ST_CURRENT_TICK"), tmp);\r
+\r
+       // メモリ情報\r
+       if (t.MemInfo.TotalMemory != 0)\r
+       {\r
+               char vv[128];\r
+\r
+               ToStr3(vv, sizeof(vv), t.MemInfo.TotalMemory);\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);\r
+               CtInsert(ct, _UU("SM_ST_TOTAL_MEMORY"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), t.MemInfo.UsedMemory);\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);\r
+               CtInsert(ct, _UU("SM_ST_USED_MEMORY"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), t.MemInfo.FreeMemory);\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);\r
+               CtInsert(ct, _UU("SM_ST_FREE_MEMORY"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), t.MemInfo.TotalPhys);\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);\r
+               CtInsert(ct, _UU("SM_ST_TOTAL_PHYS"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), t.MemInfo.UsedPhys);\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);\r
+               CtInsert(ct, _UU("SM_ST_USED_PHYS"), tmp);\r
+\r
+               ToStr3(vv, sizeof(vv), t.MemInfo.FreePhys);\r
+               UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv);\r
+               CtInsert(ct, _UU("SM_ST_FREE_PHYS"), tmp);\r
+       }\r
+\r
+       CtFree(ct, c);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// トラフィック情報を LVB に追加\r
+void CmdInsertTrafficInfo(CT *ct, TRAFFIC *t)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       char vv[128];\r
+       // 引数チェック\r
+       if (ct == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       // 送信情報\r
+       ToStr3(vv, sizeof(vv), t->Send.UnicastCount);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);\r
+       CtInsert(ct, _UU("SM_ST_SEND_UCAST_NUM"), tmp);\r
+\r
+       ToStr3(vv, sizeof(vv), t->Send.UnicastBytes);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);\r
+       CtInsert(ct, _UU("SM_ST_SEND_UCAST_SIZE"), tmp);\r
+\r
+       ToStr3(vv, sizeof(vv), t->Send.BroadcastCount);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);\r
+       CtInsert(ct, _UU("SM_ST_SEND_BCAST_NUM"), tmp);\r
+\r
+       ToStr3(vv, sizeof(vv), t->Send.BroadcastBytes);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);\r
+       CtInsert(ct, _UU("SM_ST_SEND_BCAST_SIZE"), tmp);\r
+\r
+       // 受信情報\r
+       ToStr3(vv, sizeof(vv), t->Recv.UnicastCount);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);\r
+       CtInsert(ct, _UU("SM_ST_RECV_UCAST_NUM"), tmp);\r
+\r
+       ToStr3(vv, sizeof(vv), t->Recv.UnicastBytes);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);\r
+       CtInsert(ct, _UU("SM_ST_RECV_UCAST_SIZE"), tmp);\r
+\r
+       ToStr3(vv, sizeof(vv), t->Recv.BroadcastCount);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_NUM_PACKET_STR"), vv);\r
+       CtInsert(ct, _UU("SM_ST_RECV_BCAST_NUM"), tmp);\r
+\r
+       ToStr3(vv, sizeof(vv), t->Recv.BroadcastBytes);\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_ST_SIZE_BYTE_STR"), vv);\r
+       CtInsert(ct, _UU("SM_ST_RECV_BCAST_SIZE"), tmp);\r
+}\r
+\r
+// ポート番号の入力\r
+wchar_t *CmdPromptPort(CONSOLE *c, void *param)\r
+{\r
+       wchar_t *prompt_str;\r
+\r
+       if (param != NULL)\r
+       {\r
+               prompt_str = (wchar_t *)param;\r
+       }\r
+       else\r
+       {\r
+               prompt_str = _UU("CMD_PROPMT_PORT");\r
+       }\r
+\r
+       return c->ReadLine(c, prompt_str, true);\r
+}\r
+\r
+// ポート番号の検証\r
+bool CmdEvalPort(CONSOLE *c, wchar_t *str, void *param)\r
+{\r
+       UINT i;\r
+       // 引数チェック\r
+       if (c == NULL || str == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       i = UniToInt(str);\r
+\r
+       if (i >= 1 && i <= 65535)\r
+       {\r
+               return true;\r
+       }\r
+\r
+       c->Write(c, _UU("CMD_EVAL_PORT"));\r
+\r
+       return false;\r
+}\r
+\r
+// ListenerCreate コマンド\r
+UINT PsListenerCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       PS *ps = (PS *)param;\r
+       UINT ret;\r
+       RPC_LISTENER t;\r
+       PARAM args[] =\r
+       {\r
+               {"[port]", CmdPromptPort, _UU("CMD_ListenerCreate_PortPrompt"), CmdEvalPort, NULL},\r
+       };\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.Enable = true;\r
+       t.Port = ToInt(GetParamStr(o, "[port]"));\r
+\r
+       ret = ScCreateListener(ps->Rpc, &t);\r
+\r
+       if (ret != ERR_NO_ERROR)\r
+       {\r
+               CmdPrintError(c, ret);\r
+               FreeParamValueList(o);\r
+               return ret;\r
+       }\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// About コマンド\r
+UINT PsAbout(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+\r
+       o = ParseCommandList(c, cmd_name, str, NULL, 0);\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // バージョン情報を表示する\r
+       CmdPrintAbout(c);\r
+\r
+       FreeParamValueList(o);\r
+\r
+       return 0;\r
+}\r
+\r
+// 新しいサーバー管理コンテキストの作成\r
+PS *NewPs(CONSOLE *c, RPC *rpc, char *servername, UINT serverport, char *hubname, char *adminhub, wchar_t *cmdline)\r
+{\r
+       PS *ps;\r
+       // 引数チェック\r
+       if (c == NULL || rpc == NULL || servername == NULL)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       if (IsEmptyStr(hubname))\r
+       {\r
+               hubname = NULL;\r
+       }\r
+       if (IsEmptyStr(adminhub))\r
+       {\r
+               adminhub = NULL;\r
+       }\r
+       if (UniIsEmptyStr(cmdline))\r
+       {\r
+               cmdline = NULL;\r
+       }\r
+\r
+       ps = ZeroMalloc(sizeof(PS));\r
+       ps->ConsoleForServer = true;\r
+       ps->ServerPort = serverport;\r
+       ps->ServerName = CopyStr(servername);\r
+       ps->Console = c;\r
+       ps->Rpc = rpc;\r
+       ps->HubName = CopyStr(hubname);\r
+       ps->LastError = 0;\r
+       ps->AdminHub = CopyStr(adminhub);\r
+       ps->CmdLine = CopyUniStr(cmdline);\r
+\r
+       return ps;\r
+}\r
+\r
+// サーバー管理コンテキストの解放\r
+void FreePs(PS *ps)\r
+{\r
+       // 引数チェック\r
+       if (ps == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Free(ps->HubName);\r
+       Free(ps->AdminHub);\r
+       Free(ps->CmdLine);\r
+       Free(ps->ServerName);\r
+\r
+       Free(ps);\r
+}\r
+\r
+// サーバー管理ツール\r
+UINT PsConnect(CONSOLE *c, char *host, UINT port, char *hub, char *adminhub, wchar_t *cmdline, char *password)\r
+{\r
+       UINT retcode = 0;\r
+       RPC *rpc = NULL;\r
+       CEDAR *cedar;\r
+       CLIENT_OPTION o;\r
+       UCHAR hashed_password[SHA1_SIZE];\r
+       bool b = false;\r
+       // 引数チェック\r
+       if (c == NULL || host == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+       if (port == 0)\r
+       {\r
+               port = 443;\r
+       }\r
+       if (hub != NULL)\r
+       {\r
+               adminhub = NULL;\r
+       }\r
+\r
+       cedar = NewCedar(NULL, NULL);\r
+\r
+       Zero(&o, sizeof(o));\r
+       UniStrCpy(o.AccountName, sizeof(o.AccountName), L"VPNCMD");\r
+       StrCpy(o.Hostname, sizeof(o.Hostname), host);\r
+       o.Port = port;\r
+       o.ProxyType = PROXY_DIRECT;\r
+\r
+       Hash(hashed_password, password, StrLen(password), true);\r
+\r
+       if (IsEmptyStr(password) == false)\r
+       {\r
+               b = true;\r
+       }\r
+\r
+       // 接続\r
+       while (true)\r
+       {\r
+               UINT err;\r
+\r
+               rpc = AdminConnectEx(cedar, &o, hub, hashed_password, &err, CEDAR_CUI_STR);\r
+               if (rpc == NULL)\r
+               {\r
+                       // 失敗\r
+                       retcode = err;\r
+\r
+                       if (err == ERR_ACCESS_DENIED)\r
+                       {\r
+                               char *pass;\r
+                               // パスワード違い\r
+                               if (b)\r
+                               {\r
+                                       // パスワードを入力させる\r
+                                       c->Write(c, _UU("CMD_UTVPNCMD_PASSWORD_1"));\r
+                               }\r
+\r
+                               b = true;\r
+\r
+                               pass = c->ReadPassword(c, _UU("CMD_UTVPNCMD_PASSWORD_2"));\r
+                               c->Write(c, L"");\r
+\r
+                               if (pass != NULL)\r
+                               {\r
+                                       Hash(hashed_password, pass, StrLen(pass), true);\r
+                                       Free(pass);\r
+                               }\r
+                               else\r
+                               {\r
+                                       break;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               // その他のエラー\r
+                               CmdPrintError(c, err);\r
+                               break;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       PS *ps;\r
+\r
+                       // 成功\r
+                       ps = NewPs(c, rpc, host, port, hub, adminhub, cmdline);\r
+                       PsMain(ps);\r
+                       retcode = ps->LastError;\r
+                       FreePs(ps);\r
+                       AdminDisconnect(rpc);\r
+                       break;\r
+               }\r
+       }\r
+\r
+       ReleaseCedar(cedar);\r
+\r
+       return retcode;\r
+}\r
+\r
+// エラーを表示する\r
+void CmdPrintError(CONSOLE *c, UINT err)\r
+{\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       UniFormat(tmp, sizeof(tmp), _UU("CMD_UTVPNCMD_ERROR"),\r
+               err, GetUniErrorStr(err));\r
+       c->Write(c, tmp);\r
+\r
+       if (err == ERR_DISCONNECTED)\r
+       {\r
+               c->Write(c, _UU("CMD_DISCONNECTED_MSG"));\r
+       }\r
+}\r
+\r
+// バージョン情報を表示する\r
+void CmdPrintAbout(CONSOLE *c)\r
+{\r
+       CEDAR *cedar;\r
+       wchar_t tmp[MAX_SIZE];\r
+       char exe[MAX_PATH];\r
+       // 引数チェック\r
+       if (c == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       cedar = NewCedar(NULL, NULL);\r
+\r
+       GetExeName(exe, sizeof(exe));\r
+\r
+       UniFormat(tmp, sizeof(tmp), _UU("CMD_UTVPNCMD_ABOUT"),\r
+               cedar->VerString, cedar->BuildInfo);\r
+\r
+       c->Write(c, tmp);\r
+\r
+       ReleaseCedar(cedar);\r
+}\r
+\r
+// ホスト名とポート番号をパースする (@ で区切る)\r
+bool ParseHostPortAtmark(char *src, char **host, UINT *port, UINT default_port)\r
+{\r
+       TOKEN_LIST *t;\r
+       bool ret = false;\r
+       // 引数チェック\r
+       if (src == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       t = ParseToken(src, "@");\r
+       if (t == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (port != NULL)\r
+       {\r
+               *port = 0;\r
+       }\r
+\r
+       if (default_port == 0)\r
+       {\r
+               if (t->NumTokens < 2)\r
+               {\r
+                       FreeToken(t);\r
+                       return false;\r
+               }\r
+\r
+               if (ToInt(t->Token[1]) == 0)\r
+               {\r
+                       FreeToken(t);\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       if (t->NumTokens >= 2 && ToInt(t->Token[1]) == 0)\r
+       {\r
+               FreeToken(t);\r
+               return false;\r
+       }\r
+\r
+       if (t->NumTokens >= 1 && IsEmptyStr(t->Token[0]) == false)\r
+       {\r
+               ret = true;\r
+\r
+               if (host != NULL)\r
+               {\r
+                       *host = CopyStr(t->Token[0]);\r
+                       Trim(*host);\r
+               }\r
+\r
+               if (t->NumTokens >= 2)\r
+               {\r
+                       if (port != NULL)\r
+                       {\r
+                               *port = ToInt(t->Token[1]);\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (port != NULL)\r
+       {\r
+               if (*port == 0)\r
+               {\r
+                       *port = default_port;\r
+               }\r
+       }\r
+\r
+       FreeToken(t);\r
+\r
+       return ret;\r
+}\r
+\r
+// ホスト名とポート番号をパースする\r
+bool ParseHostPort(char *src, char **host, UINT *port, UINT default_port)\r
+{\r
+       TOKEN_LIST *t;\r
+       bool ret = false;\r
+       // 引数チェック\r
+       if (src == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (StartWith(src, "["))\r
+       {\r
+               if (InStr(src, "]"))\r
+               {\r
+                       // [target]:port の形式\r
+                       UINT i, n;\r
+                       char tmp[MAX_SIZE];\r
+\r
+                       StrCpy(tmp, sizeof(tmp), src);\r
+\r
+                       n = SearchStrEx(tmp, "]", 0, false);\r
+                       if (n != INFINITE)\r
+                       {\r
+                               UINT len = StrLen(tmp);\r
+\r
+                               for (i = n;i < len;i++)\r
+                               {\r
+                                       if (tmp[i] == ':')\r
+                                       {\r
+                                               tmp[i] = '@';\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       return ParseHostPortAtmark(tmp, host, port, default_port);\r
+               }\r
+       }\r
+\r
+       if (InStr(src, "@"))\r
+       {\r
+               // @ で区切られている\r
+               return ParseHostPortAtmark(src, host, port, default_port);\r
+       }\r
+\r
+       t = ParseToken(src, ":");\r
+       if (t == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       if (port != NULL)\r
+       {\r
+               *port = 0;\r
+       }\r
+\r
+       if (default_port == 0)\r
+       {\r
+               if (t->NumTokens < 2)\r
+               {\r
+                       FreeToken(t);\r
+                       return false;\r
+               }\r
+\r
+               if (ToInt(t->Token[1]) == 0)\r
+               {\r
+                       FreeToken(t);\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       if (t->NumTokens >= 2 && ToInt(t->Token[1]) == 0)\r
+       {\r
+               FreeToken(t);\r
+               return false;\r
+       }\r
+\r
+       if (t->NumTokens >= 1 && IsEmptyStr(t->Token[0]) == false)\r
+       {\r
+               ret = true;\r
+\r
+               if (host != NULL)\r
+               {\r
+                       *host = CopyStr(t->Token[0]);\r
+                       Trim(*host);\r
+               }\r
+\r
+               if (t->NumTokens >= 2)\r
+               {\r
+                       if (port != NULL)\r
+                       {\r
+                               *port = ToInt(t->Token[1]);\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (port != NULL)\r
+       {\r
+               if (*port == 0)\r
+               {\r
+                       *port = default_port;\r
+               }\r
+       }\r
+\r
+       FreeToken(t);\r
+\r
+       return ret;\r
+}\r
+\r
+// vpncmd コマンドプロシージャ\r
+UINT VpnCmdProc(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)\r
+{\r
+       LIST *o;\r
+       char *target;\r
+       bool server = false;\r
+       bool client = false;\r
+       bool tools = false;\r
+       char *hostname = NULL;\r
+       char *password;\r
+       wchar_t *cmdline;\r
+       bool host_inputted = false;\r
+       UINT port = 0;\r
+       UINT retcode = 0;\r
+       PARAM args[] =\r
+       {\r
+               {"[host:port]", NULL, NULL, NULL, NULL},\r
+               {"CLIENT", NULL, NULL, NULL, NULL},\r
+               {"SERVER", NULL, NULL, NULL, NULL},\r
+               {"TOOLS", NULL, NULL, NULL, NULL},\r
+               {"HUB", NULL, NULL, NULL, NULL},\r
+               {"ADMINHUB", NULL, NULL, NULL, NULL},\r
+               {"PASSWORD", NULL, NULL, NULL, NULL},\r
+               {"IN", NULL, NULL, NULL, NULL},\r
+               {"OUT", NULL, NULL, NULL, NULL},\r
+               {"CMD", NULL, NULL, NULL, NULL},\r
+               {"CSV", NULL, NULL, NULL, NULL},\r
+       };\r
+\r
+       if (c->ConsoleType == CONSOLE_LOCAL)\r
+       {\r
+               // 起動パス情報の初期化\r
+               VpnCmdInitBootPath();\r
+       }\r
+\r
+       if(c->ConsoleType != CONSOLE_CSV)\r
+       {\r
+               CmdPrintAbout(c);\r
+               c->Write(c, L"");\r
+       }\r
+\r
+       o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));\r
+\r
+       if (o == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // Client か Server か Tools かの指定\r
+       if ((GetParamStr(o, "CLIENT") == NULL && GetParamStr(o, "SERVER") == NULL && GetParamStr(o, "TOOLS") == NULL) ||\r
+               (GetParamStr(o, "CLIENT") != NULL && GetParamStr(o, "SERVER") != NULL && GetParamStr(o, "TOOLS") != NULL))\r
+       {\r
+               wchar_t *ret;\r
+               UINT code;\r
+               // Client か Server か Tools かが指定されていない\r
+               c->Write(c, _UU("CMD_UTVPNCMD_CS_1"));\r
+\r
+               ret = c->ReadLine(c, _UU("CMD_UTVPNCMD_CS_2"), true);\r
+\r
+               code = UniToInt(ret);\r
+               Free(ret);\r
+\r
+               switch (code)\r
+               {\r
+               case 1:\r
+                       // Server\r
+                       server = true;\r
+                       break;\r
+\r
+               case 2:\r
+                       // Client\r
+                       client = true;\r
+                       break;\r
+\r
+               case 3:\r
+                       // Tools\r
+                       tools = true;\r
+                       break;\r
+\r
+               default:\r
+                       // 指定無し\r
+                       FreeParamValueList(o);\r
+                       return ERR_USER_CANCEL;\r
+               }\r
+\r
+               c->Write(c, L"");\r
+       }\r
+       else\r
+       {\r
+               if (GetParamStr(o, "SERVER") != NULL)\r
+               {\r
+                       server = true;\r
+               }\r
+               else if (GetParamStr(o, "CLIENT") != NULL)\r
+               {\r
+                       client = true;\r
+               }\r
+               else\r
+               {\r
+                       tools = true;\r
+               }\r
+       }\r
+\r
+       // 接続先ホスト名\r
+       target = CopyStr(GetParamStr(o, "[host:port]"));\r
+\r
+       if (target == NULL && tools == false)\r
+       {\r
+               wchar_t *str;\r
+               // ホスト名を入力させる\r
+               if (server)\r
+               {\r
+                       c->Write(c, _UU("CMD_UTVPNCMD_HOST_1"));\r
+               }\r
+               else if (client)\r
+               {\r
+                       c->Write(c, _UU("CMD_UTVPNCMD_HOST_2"));\r
+               }\r
+\r
+               str = c->ReadLine(c, _UU("CMD_UTVPNCMD_HOST_3"), true);\r
+               c->Write(c, L"");\r
+               target = CopyUniToStr(str);\r
+               Free(str);\r
+\r
+               if (target == NULL)\r
+               {\r
+                       // キャンセル\r
+                       FreeParamValueList(o);\r
+                       return ERR_USER_CANCEL;\r
+               }\r
+\r
+               if (IsEmptyStr(target))\r
+               {\r
+                       Free(target);\r
+                       target = CopyStr("localhost");\r
+               }\r
+       }\r
+       else\r
+       {\r
+               // ユーザーがホスト名を指定した\r
+               host_inputted = true;\r
+       }\r
+\r
+       if (tools == false)\r
+       {\r
+               if (ParseHostPort(target, &hostname, &port, 443) == false)\r
+               {\r
+                       c->Write(c, _UU("CMD_MSG_INVALID_HOSTNAME"));\r
+                       Free(target);\r
+                       FreeParamValueList(o);\r
+                       return ERR_INVALID_PARAMETER;\r
+               }\r
+       }\r
+\r
+       // パスワード\r
+       password = GetParamStr(o, "PASSWORD");\r
+       if (password == NULL)\r
+       {\r
+               password = "";\r
+       }\r
+\r
+       // コマンドライン\r
+       cmdline = GetParamUniStr(o, "CMD");\r
+\r
+       if (server)\r
+       {\r
+               // サーバーとしての処理\r
+               char *hub;\r
+               char *adminhub = NULL;\r
+\r
+               hub = CopyStr(GetParamStr(o, "HUB"));\r
+               adminhub = GetParamStr(o, "ADMINHUB");\r
+\r
+               // 仮想 HUB 管理モードで指定する仮想 HUB を決定する\r
+               if (hub == NULL)\r
+               {\r
+                       if (host_inputted == false)\r
+                       {\r
+                               wchar_t *s;\r
+                               // ユーザーがホスト名をコマンドラインで指定していない場合は\r
+                               // プロンプトを表示して仮想 HUB 名も取得する\r
+                               c->Write(c, _UU("CMD_UTVPNCMD_HUB_1"));\r
+\r
+                               s = c->ReadLine(c, _UU("CMD_UTVPNCMD_HUB_2"), true);\r
+\r
+                               hub = CopyUniToStr(s);\r
+                               Free(s);\r
+                       }\r
+               }\r
+\r
+               if (IsEmptyStr(hub))\r
+               {\r
+                       Free(hub);\r
+                       hub = NULL;\r
+               }\r
+               if (IsEmptyStr(adminhub))\r
+               {\r
+                       adminhub = NULL;\r
+               }\r
+\r
+               retcode = PsConnect(c, hostname, port, hub, adminhub, cmdline, password);\r
+\r
+               Free(hub);\r
+       }\r
+       else if (client)\r
+       {\r
+               // クライアントとしての処理\r
+               Trim(target);\r
+\r
+               retcode = PcConnect(c, target, cmdline, password);\r
+       }\r
+       else if (tools)\r
+       {\r
+               // VPN Tools として処理\r
+               retcode = PtConnect(c, cmdline);\r
+       }\r
+\r
+       Free(hostname);\r
+       Free(target);\r
+       FreeParamValueList(o);\r
+\r
+       return retcode;\r
+}\r
+\r
+// vpncmd のエントリポイント\r
+UINT CommandMain(wchar_t *command_line)\r
+{\r
+       UINT ret = 0;\r
+       wchar_t *infile, *outfile;\r
+       char *a_infile, *a_outfile;\r
+       wchar_t *csvmode;\r
+       CONSOLE *c;\r
+\r
+       // 引数チェック\r
+       if (command_line == NULL)\r
+       {\r
+               return ERR_INVALID_PARAMETER;\r
+       }\r
+\r
+       // /in と /out の項目だけ先読みする\r
+       infile = ParseCommand(command_line, L"in");\r
+       outfile = ParseCommand(command_line, L"out");\r
+       if (UniIsEmptyStr(infile))\r
+       {\r
+               Free(infile);\r
+               infile = NULL;\r
+       }\r
+       if (UniIsEmptyStr(outfile))\r
+       {\r
+               Free(outfile);\r
+               outfile = NULL;\r
+       }\r
+\r
+       a_infile = CopyUniToStr(infile);\r
+       a_outfile = CopyUniToStr(outfile);\r
+\r
+       // ローカルコンソールの確保\r
+       c = NewLocalConsole(infile, outfile);\r
+       if (c != NULL)\r
+       {\r
+               // vpncmd コマンドの定義\r
+               CMD cmd[] =\r
+               {\r
+                       {"utvpncmd", VpnCmdProc},\r
+               };\r
+\r
+               // CSV モードを先読みしてチェック\r
+               csvmode = ParseCommand(command_line, L"csv");\r
+               if(csvmode != NULL)\r
+               {\r
+                       Free(csvmode);\r
+                       c->ConsoleType = CONSOLE_CSV;\r
+               }\r
+\r
+               if (DispatchNextCmdEx(c, command_line, ">", cmd, sizeof(cmd) / sizeof(cmd[0]), NULL) == false)\r
+               {\r
+                       ret = ERR_INVALID_PARAMETER;\r
+               }\r
+               else\r
+               {\r
+                       ret = c->RetCode;\r
+               }\r
+\r
+               // ローカルコンソールの解放\r
+               c->Free(c);\r
+       }\r
+       else\r
+       {\r
+               Print("Error: Couldn't open local console.\n");\r
+       }\r
+\r
+       Free(a_infile);\r
+       Free(a_outfile);\r
+       Free(infile);\r
+       Free(outfile);\r
+\r
+       return ret;\r
+}\r
+\r