* tar xzf utvpn-src-unix-v101-7101-public-2010.06.27.tar.gz
[lab.git] / utvpn / utvpn-unix-v101-7101-public / src / Cedar / NM.c
diff --git a/utvpn/utvpn-unix-v101-7101-public/src/Cedar/NM.c b/utvpn/utvpn-unix-v101-7101-public/src/Cedar/NM.c
new file mode 100644 (file)
index 0000000..7d0ae37
--- /dev/null
@@ -0,0 +1,1483 @@
+// 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
+// NM.c\r
+// Win32 用 SoftEther UT-VPN User-mode Router Manager\r
+\r
+\r
+#ifdef WIN32\r
+\r
+#define        SM_C\r
+#define        CM_C\r
+#define        NM_C\r
+\r
+#define        _WIN32_WINNT            0x0502\r
+#define        WINVER                          0x0502\r
+#include <winsock2.h>\r
+#include <windows.h>\r
+#include <wincrypt.h>\r
+#include <wininet.h>\r
+#include <shlobj.h>\r
+#include <commctrl.h>\r
+#include <Dbghelp.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <wchar.h>\r
+#include <stdarg.h>\r
+#include <time.h>\r
+#include <errno.h>\r
+#include <Mayaqua/Mayaqua.h>\r
+#include <Cedar/Cedar.h>\r
+#include "CMInner.h"\r
+#include "SMInner.h"\r
+#include "NMInner.h"\r
+#include "../PenCore/resource.h"\r
+\r
+// グローバル変数\r
+static NM *nm = NULL;\r
+\r
+\r
+// パスワード変更ダイアログ\r
+UINT NmChangePasswordProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       RPC *r = (RPC *)param;\r
+       char tmp1[MAX_SIZE];\r
+       char tmp2[MAX_SIZE];\r
+       RPC_SET_PASSWORD t;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               FormatText(hWnd, 0, r->Sock->RemoteHostname);\r
+               FormatText(hWnd, S_TITLE, r->Sock->RemoteHostname);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1));\r
+               GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2));\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_PASSWORD1:\r
+               case E_PASSWORD2:\r
+                       SetEnable(hWnd, IDOK, StrCmp(tmp1, tmp2) == 0);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       Zero(&t, sizeof(t));\r
+                       Hash(t.HashedPassword, tmp1, StrLen(tmp1), true);\r
+\r
+                       if (CALL(hWnd, NcSetPassword(r, &t)))\r
+                       {\r
+                               MsgBox(hWnd, MB_ICONINFORMATION, _UU("NM_PASSWORD_MSG"));\r
+                               EndDialog(hWnd, true);\r
+                       }\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// パスワードの変更\r
+void NmChangePassword(HWND hWnd, RPC *r)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || r == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_NM_CHANGE_PASSWORD, NmChangePasswordProc, r);\r
+}\r
+\r
+// DHCP 列挙初期化\r
+void NmDhcpInit(HWND hWnd, SM_HUB *r)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || r == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_INTERNET);\r
+\r
+       LvInit(hWnd, L_TABLE);\r
+       LvInsertColumn(hWnd, L_TABLE, 0, _UU("DHCP_DHCP_ID"), 50);\r
+       LvInsertColumn(hWnd, L_TABLE, 1, _UU("DHCP_LEASED_TIME"), 200);\r
+       LvInsertColumn(hWnd, L_TABLE, 2, _UU("DHCP_EXPIRE_TIME"), 200);\r
+       LvInsertColumn(hWnd, L_TABLE, 3, _UU("DHCP_MAC_ADDRESS"), 130);\r
+       LvInsertColumn(hWnd, L_TABLE, 4, _UU("DHCP_IP_ADDRESS"), 100);\r
+       LvInsertColumn(hWnd, L_TABLE, 5, _UU("DHCP_HOSTNAME"), 150);\r
+\r
+       NmDhcpRefresh(hWnd, r);\r
+}\r
+\r
+// DHCP 列挙\r
+void NmDhcpRefresh(HWND hWnd, SM_HUB *r)\r
+{\r
+       LVB *b;\r
+       RPC_ENUM_DHCP t;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || r == NULL)\r
+       {\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), r->HubName);\r
+\r
+       if (CALL(hWnd, ScEnumDHCP(r->Rpc, &t)) == false)\r
+       {\r
+               return;\r
+       }\r
+\r
+       b = LvInsertStart();\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
+               LvInsertAdd(b, ICO_INTERNET, NULL, 6,\r
+                       tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_TABLE);\r
+\r
+       FreeRpcEnumDhcp(&t);\r
+}\r
+\r
+// DHCP 列挙プロシージャ\r
+UINT NmDhcpProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_HUB *r = (SM_HUB *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               NmDhcpInit(hWnd, r);\r
+               SetTimer(hWnd, 1, NM_DHCP_REFRESH_TIME, NULL);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case B_REFRESH:\r
+                       NmDhcpRefresh(hWnd, r);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       KillTimer(hWnd, 1);\r
+                       NmDhcpRefresh(hWnd, r);\r
+                       SetTimer(hWnd, 1, NM_DHCP_REFRESH_TIME, NULL);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_TABLE);\r
+\r
+       return 0;\r
+}\r
+\r
+// DHCP 列挙\r
+void NmDhcp(HWND hWnd, SM_HUB *r)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || r == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_NM_DHCP, NmDhcpProc, r);\r
+}\r
+\r
+\r
+// NAT 列挙初期化\r
+void NmNatInit(HWND hWnd, SM_HUB *r)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || r == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_PROTOCOL);\r
+\r
+       LvInit(hWnd, L_TABLE);\r
+       LvInsertColumn(hWnd, L_TABLE, 0, _UU("NM_NAT_ID"), 50);\r
+       LvInsertColumn(hWnd, L_TABLE, 1, _UU("NM_NAT_PROTOCOL"), 80);\r
+       LvInsertColumn(hWnd, L_TABLE, 2, _UU("NM_NAT_SRC_HOST"), 100);\r
+       LvInsertColumn(hWnd, L_TABLE, 3, _UU("NM_NAT_SRC_PORT"), 80);\r
+       LvInsertColumn(hWnd, L_TABLE, 4, _UU("NM_NAT_DST_HOST"), 150);\r
+       LvInsertColumn(hWnd, L_TABLE, 5, _UU("NM_NAT_DST_PORT"), 80);\r
+       LvInsertColumn(hWnd, L_TABLE, 6, _UU("NM_NAT_CREATED"), 200);\r
+       LvInsertColumn(hWnd, L_TABLE, 7, _UU("NM_NAT_LAST_COMM"), 200);\r
+       LvInsertColumn(hWnd, L_TABLE, 8, _UU("NM_NAT_SIZE"), 120);\r
+       LvInsertColumn(hWnd, L_TABLE, 9, _UU("NM_NAT_TCP_STATUS"), 120);\r
+\r
+       NmNatRefresh(hWnd, r);\r
+}\r
+\r
+// NAT 列挙\r
+void NmNatRefresh(HWND hWnd, SM_HUB *r)\r
+{\r
+       LVB *b;\r
+       RPC_ENUM_NAT t;\r
+       UINT i;\r
+       // 引数チェック\r
+       if (hWnd == NULL || r == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), r->HubName);\r
+\r
+       if (CALL(hWnd, ScEnumNAT(r->Rpc, &t)) == false)\r
+       {\r
+               Close(hWnd);\r
+               return;\r
+       }\r
+\r
+       b = LvInsertStart();\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
+               LvInsertAdd(b, ICO_PROTOCOL, NULL, 10,\r
+                       tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9);\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_TABLE);\r
+\r
+       FreeRpcEnumNat(&t);\r
+}\r
+\r
+// NAT 列挙プロシージャ\r
+UINT NmNatProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_HUB *r = (SM_HUB *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               NmNatInit(hWnd, r);\r
+               SetTimer(hWnd, 1, NM_NAT_REFRESH_TIME, NULL);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+\r
+               case B_REFRESH:\r
+                       NmNatRefresh(hWnd, r);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       KillTimer(hWnd, 1);\r
+                       NmNatRefresh(hWnd, r);\r
+                       SetTimer(hWnd, 1, NM_NAT_REFRESH_TIME, NULL);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       LvStandardHandler(hWnd, msg, wParam, lParam, L_TABLE);\r
+\r
+       return 0;\r
+}\r
+\r
+// NAT 列挙\r
+void NmNat(HWND hWnd, SM_HUB *r)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || r == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_NM_NAT, NmNatProc, r);\r
+}\r
+\r
+// ルーターの情報の表示\r
+bool NmInfo(HWND hWnd, SM_SERVER *s, void *param)\r
+{\r
+       LVB *b;\r
+       RPC_NAT_INFO t;\r
+       wchar_t tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       if (CALL(hWnd, NcGetInfo(s->Rpc, &t)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.NatProductName);\r
+       LvInsertAdd(b, ICO_ROUTER, NULL, 2, _UU("NM_INFO_PRODUCT_NAME"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.NatVersionString);\r
+       LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("NM_INFO_VERSION_STR"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.NatBuildInfoString);\r
+       LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("NM_INFO_BUILD_INFO"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.NatHostName);\r
+       LvInsertAdd(b, ICO_TOWER, NULL, 2, _UU("NM_INFO_HOSTNAME"), tmp);\r
+\r
+       // OS\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.OsSystemName);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_SYSTEM_NAME"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.OsProductName);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _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
+               LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_SERVICE_PACK"), tmp);\r
+       }\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.OsVendorName);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_VENDER_NAME"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.OsVersion);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_VERSION"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.KernelName);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_KERNEL_NAME"), tmp);\r
+\r
+       StrToUni(tmp, sizeof(tmp), t.OsInfo.KernelVersion);\r
+       LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_KERNEL_VERSION"), 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
+               LvInsertAdd(b, ICO_MEMORY, NULL, 2, _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
+               LvInsertAdd(b, ICO_MEMORY, NULL, 2, _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
+               LvInsertAdd(b, ICO_MEMORY, NULL, 2, _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
+               LvInsertAdd(b, ICO_MEMORY, NULL, 2, _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
+               LvInsertAdd(b, ICO_MEMORY, NULL, 2, _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
+               LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_FREE_PHYS"), tmp);\r
+       }\r
+\r
+       LvInsertEnd(b, hWnd, L_STATUS);\r
+\r
+       FreeRpcNatInfo(&t);\r
+\r
+       return true;\r
+}\r
+\r
+// ルータの状況の表示\r
+bool NmStatus(HWND hWnd, SM_SERVER *s, void *param)\r
+{\r
+       LVB *b;\r
+       RPC_NAT_STATUS t;\r
+       wchar_t tmp[MAX_SIZE];\r
+       SM_HUB *h = (SM_HUB *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL || s == NULL)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+\r
+       StrCpy(t.HubName, sizeof(t.HubName), h->HubName);\r
+\r
+       if (CALL(hWnd, ScGetSecureNATStatus(s->Rpc, &t)) == false)\r
+       {\r
+               return false;\r
+       }\r
+\r
+       b = LvInsertStart();\r
+\r
+       StrToUni(tmp, sizeof(tmp), h->HubName);\r
+       LvInsertAdd(b, ICO_HUB, NULL, 2, _UU("SM_HUB_COLUMN_1"), tmp);\r
+\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumTcpSessions);\r
+       LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("NM_STATUS_TCP"), tmp);\r
+\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumUdpSessions);\r
+       LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("NM_STATUS_UDP"), tmp);\r
+\r
+       UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_CLIENT"), t.NumDhcpClients);\r
+       LvInsertAdd(b, ICO_PROTOCOL_DHCP, NULL, 2, _UU("NM_STATUS_DHCP"), tmp);\r
+\r
+       LvInsertEnd(b, hWnd, L_STATUS);\r
+\r
+       FreeRpcNatStatus(&t);\r
+\r
+       return true;\r
+}\r
+\r
+// フォームの内容を VH_OPTION に変換\r
+void NmEditVhOptionFormToVH(HWND hWnd, VH_OPTION *t)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       BUF *b;\r
+       // 引数チェック\r
+       if (hWnd == NULL || t == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(t, sizeof(VH_OPTION));\r
+\r
+       GetTxtA(hWnd, E_MAC, tmp, sizeof(tmp));\r
+       b = StrToBin(tmp);\r
+       if (b != NULL)\r
+       {\r
+               if (b->Size == 6)\r
+               {\r
+                       Copy(t->MacAddress, b->Buf, 6);\r
+               }\r
+               FreeBuf(b);\r
+       }\r
+\r
+       UINTToIP(&t->Ip, IpGet(hWnd, E_IP));\r
+       UINTToIP(&t->Mask, IpGet(hWnd, E_MASK));\r
+\r
+       t->UseNat = IsChecked(hWnd, R_USE_NAT);\r
+       t->Mtu = GetInt(hWnd, E_MTU);\r
+       t->NatTcpTimeout = GetInt(hWnd, E_TCP);\r
+       t->NatUdpTimeout = GetInt(hWnd, E_UDP);\r
+\r
+       t->UseDhcp = IsChecked(hWnd, R_USE_DHCP);\r
+       UINTToIP(&t->DhcpLeaseIPStart, IpGet(hWnd, E_DHCP_START));\r
+       UINTToIP(&t->DhcpLeaseIPEnd, IpGet(hWnd, E_DHCP_END));\r
+       UINTToIP(&t->DhcpSubnetMask, IpGet(hWnd, E_DHCP_MASK));\r
+       t->DhcpExpireTimeSpan = GetInt(hWnd, E_EXPIRES);\r
+       UINTToIP(&t->DhcpGatewayAddress, IpGet(hWnd, E_GATEWAY));\r
+       UINTToIP(&t->DhcpDnsServerAddress, IpGet(hWnd, E_DNS));\r
+       GetTxtA(hWnd, E_DOMAIN, t->DhcpDomainName, sizeof(t->DhcpDomainName));\r
+       t->SaveLog = IsChecked(hWnd, R_SAVE_LOG);\r
+}\r
+\r
+// 初期化\r
+void NmEditVhOptionInit(HWND hWnd, SM_HUB *r)\r
+{\r
+       char tmp[MAX_SIZE];\r
+       VH_OPTION t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || r == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       FormatText(hWnd, S_TITLE, r->HubName);\r
+\r
+       Zero(&t, sizeof(VH_OPTION));\r
+       StrCpy(t.HubName, sizeof(t.HubName), r->HubName);\r
+       if (CALL(hWnd, ScGetSecureNATOption(r->Rpc, &t)) == false)\r
+       {\r
+               EndDialog(hWnd, false);\r
+               return;\r
+       }\r
+\r
+       if (GetCapsBool(r->p->CapsList, "b_virtual_nat_disabled"))\r
+       {\r
+               SetEnable(hWnd, R_USE_NAT, false);\r
+               Check(hWnd, R_USE_NAT, false);\r
+       }\r
+\r
+       MacToStr(tmp, sizeof(tmp), t.MacAddress);\r
+       SetTextA(hWnd, E_MAC, tmp);\r
+       IpSet(hWnd, E_IP, IPToUINT(&t.Ip));\r
+       IpSet(hWnd, E_MASK, IPToUINT(&t.Mask));\r
+\r
+       Check(hWnd, R_USE_NAT, t.UseNat);\r
+       SetIntEx(hWnd, E_MTU, t.Mtu);\r
+       SetIntEx(hWnd, E_TCP, t.NatTcpTimeout);\r
+       SetIntEx(hWnd, E_UDP, t.NatUdpTimeout);\r
+\r
+       Check(hWnd, R_USE_DHCP, t.UseDhcp);\r
+       IpSet(hWnd, E_DHCP_START, IPToUINT(&t.DhcpLeaseIPStart));\r
+       IpSet(hWnd, E_DHCP_END, IPToUINT(&t.DhcpLeaseIPEnd));\r
+       IpSet(hWnd, E_DHCP_MASK, IPToUINT(&t.DhcpSubnetMask));\r
+       SetIntEx(hWnd, E_EXPIRES, t.DhcpExpireTimeSpan);\r
+\r
+       if (IPToUINT(&t.DhcpGatewayAddress) != 0)\r
+       {\r
+               IpSet(hWnd, E_GATEWAY, IPToUINT(&t.DhcpGatewayAddress));\r
+       }\r
+\r
+       if (IPToUINT(&t.DhcpDnsServerAddress) != 0)\r
+       {\r
+               IpSet(hWnd, E_DNS, IPToUINT(&t.DhcpDnsServerAddress));\r
+       }\r
+\r
+       SetTextA(hWnd, E_DOMAIN, t.DhcpDomainName);\r
+       Check(hWnd, R_SAVE_LOG, t.SaveLog);\r
+\r
+       NmEditVhOptionUpdate(hWnd, r);\r
+\r
+}\r
+\r
+void NmEditVhOptionUpdate(HWND hWnd, SM_HUB *r)\r
+{\r
+       VH_OPTION t;\r
+       bool ok = true;\r
+       // 引数チェック\r
+       if (hWnd == NULL || r == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       NmEditVhOptionFormToVH(hWnd, &t);\r
+\r
+       if (IsZero(t.MacAddress, 6))\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       if (IPToUINT(&t.Ip) == 0 || IPToUINT(&t.Mask) == 0)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       if (IpIsFilled(hWnd, E_IP) == false || IpIsFilled(hWnd, E_MASK) == false)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       if (IsHostIPAddress4(&t.Ip) == false || IsSubnetMask4(&t.Mask) == false)\r
+       {\r
+               ok = false;\r
+       }\r
+\r
+       if (t.UseNat)\r
+       {\r
+               if (t.Mtu < 64 || t.Mtu > 1500)\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               if (t.NatTcpTimeout < (NAT_TCP_MIN_TIMEOUT / 1000) || t.NatTcpTimeout > (NAT_TCP_MAX_TIMEOUT / 1000))\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               if (t.NatUdpTimeout < (NAT_UDP_MIN_TIMEOUT / 1000) || t.NatUdpTimeout > (NAT_UDP_MAX_TIMEOUT / 1000))\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       if (t.UseDhcp)\r
+       {\r
+               if (IpIsFilled(hWnd, E_DHCP_START) == false || IpIsFilled(hWnd, E_DHCP_END) == false ||\r
+                       IpIsFilled(hWnd, E_DHCP_MASK) == false)\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               if (IpGetFilledNum(hWnd, E_GATEWAY) != 0 && IpGetFilledNum(hWnd, E_GATEWAY) != 4)\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               if (IpGetFilledNum(hWnd, E_DNS) != 0 && IpGetFilledNum(hWnd, E_DNS) != 4)\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               if (IPToUINT(&t.DhcpLeaseIPStart) == 0 || IPToUINT(&t.DhcpLeaseIPEnd) == 0 ||\r
+                       IPToUINT(&t.DhcpSubnetMask) == 0)\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               if (t.DhcpExpireTimeSpan < 15)\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               if (Endian32(IPToUINT(&t.DhcpLeaseIPStart)) > Endian32(IPToUINT(&t.DhcpLeaseIPEnd)))\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               if (IsHostIPAddress4(&t.DhcpLeaseIPStart) == false ||\r
+                       IsHostIPAddress4(&t.DhcpLeaseIPEnd) == false)\r
+               {\r
+                       ok = false;\r
+               }\r
+\r
+               if (IsSubnetMask4(&t.DhcpSubnetMask) == false)\r
+               {\r
+                       ok = false;\r
+               }\r
+       }\r
+\r
+       SetEnable(hWnd, E_MTU, t.UseNat);\r
+       SetEnable(hWnd, E_TCP, t.UseNat);\r
+       SetEnable(hWnd, E_UDP, t.UseNat);\r
+\r
+       SetEnable(hWnd, E_DHCP_START, t.UseDhcp);\r
+       SetEnable(hWnd, E_DHCP_END, t.UseDhcp);\r
+       SetEnable(hWnd, E_DHCP_MASK, t.UseDhcp);\r
+       SetEnable(hWnd, E_EXPIRES, t.UseDhcp);\r
+       SetEnable(hWnd, E_GATEWAY, t.UseDhcp);\r
+       SetEnable(hWnd, E_DNS, t.UseDhcp);\r
+       SetEnable(hWnd, E_DOMAIN, t.UseDhcp);\r
+\r
+       SetEnable(hWnd, IDOK, ok);\r
+}\r
+\r
+// OK ボタン\r
+void NmEditVhOptionOnOk(HWND hWnd, SM_HUB *r)\r
+{\r
+       VH_OPTION t;\r
+       // 引数チェック\r
+       if (hWnd == NULL || r == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       NmEditVhOptionFormToVH(hWnd, &t);\r
+       StrCpy(t.HubName, sizeof(t.HubName), r->HubName);\r
+\r
+       if (CALL(hWnd, ScSetSecureNATOption(r->Rpc, &t)))\r
+       {\r
+               EndDialog(hWnd, true);\r
+       }\r
+}\r
+\r
+// 仮想ホストオプション編集ダイアログ\r
+UINT NmEditVhOptionProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       SM_HUB *r = (SM_HUB *)param;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               NmEditVhOptionInit(hWnd, r);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (LOWORD(wParam))\r
+               {\r
+               case E_MAC:\r
+               case E_IP:\r
+               case E_MASK:\r
+               case R_USE_NAT:\r
+               case E_MTU:\r
+               case E_TCP:\r
+               case E_UDP:\r
+               case R_SAVE_LOG:\r
+               case R_USE_DHCP:\r
+               case E_DHCP_START:\r
+               case E_DHCP_END:\r
+               case E_DHCP_MASK:\r
+               case E_EXPIRES:\r
+               case E_GATEWAY:\r
+               case E_DNS:\r
+               case E_DOMAIN:\r
+                       NmEditVhOptionUpdate(hWnd, r);\r
+                       break;\r
+               }\r
+\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       NmEditVhOptionOnOk(hWnd, r);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       EndDialog(hWnd, false);\r
+                       break;\r
+\r
+               case R_USE_NAT:\r
+                       if (IsChecked(hWnd, R_USE_NAT))\r
+                       {\r
+                               FocusEx(hWnd, E_MTU);\r
+                       }\r
+\r
+                       if (IsChecked(hWnd, R_USE_DHCP))\r
+                       {\r
+                               Focus(hWnd, E_DHCP_START);\r
+                       }\r
+                       break;\r
+               }\r
+\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// 仮想ホストオプションの編集\r
+void NmEditVhOption(HWND hWnd, SM_HUB *r)\r
+{\r
+       // 引数チェック\r
+       if (hWnd == NULL || r == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(hWnd, D_NM_OPTION, NmEditVhOptionProc, r);\r
+}\r
+\r
+// クライアント設定の編集\r
+void NmEditClientConfig(HWND hWnd, RPC *r)\r
+{\r
+       CM_ACCOUNT a;\r
+       RPC_CREATE_LINK t;\r
+       bool ret = false;\r
+       // 引数チェック\r
+       if (hWnd == NULL || r == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&a, sizeof(a));\r
+       Zero(&t, sizeof(t));\r
+\r
+       a.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));\r
+       a.NatMode = true;\r
+       a.Rpc = r;\r
+\r
+       if (CALLEX(hWnd, NcGetClientConfig(r, &t)) != ERR_NO_ERROR)\r
+       {\r
+               // 新規作成\r
+               a.ClientOption->Port = 443;\r
+               a.ClientOption->RetryInterval = 15;\r
+               a.ClientOption->NumRetry = INFINITE;\r
+               a.ClientOption->AdditionalConnectionInterval = 1;\r
+               a.ClientOption->UseEncrypt = true;\r
+               a.ClientOption->NoRoutingTracking = true;\r
+               a.ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));\r
+               a.ClientAuth->AuthType = CLIENT_AUTHTYPE_PASSWORD;\r
+       }\r
+       else\r
+       {\r
+               // 編集\r
+               a.EditMode = true;\r
+               Copy(a.ClientOption, t.ClientOption, sizeof(CLIENT_OPTION));\r
+               a.ClientAuth = CopyClientAuth(t.ClientAuth);\r
+\r
+               FreeRpcCreateLink(&t);\r
+       }\r
+\r
+       ret = CmEditAccountDlg(hWnd, &a);\r
+\r
+       Free(a.ServerCert);\r
+       Free(a.ClientOption);\r
+       CiFreeClientAuth(a.ClientAuth);\r
+}\r
+\r
+// 初期化\r
+void NmMainDlgInit(HWND hWnd, RPC *r)\r
+{\r
+       // 引数チェック\r
+       if (r == NULL || hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       SetIcon(hWnd, 0, ICO_ROUTER);\r
+       FormatText(hWnd, 0, r->Sock->RemoteHostname);\r
+       DlgFont(hWnd, S_STATUS, 11, true);\r
+\r
+       NmMainDlgRefresh(hWnd, r);\r
+}\r
+\r
+// 更新\r
+void NmMainDlgRefresh(HWND hWnd, RPC *r)\r
+{\r
+#if    0\r
+       RPC_NAT_STATUS t;\r
+       wchar_t tmp[MAX_SIZE];\r
+       wchar_t tmp2[MAX_SIZE];\r
+       // 引数チェック\r
+       if (r == NULL || hWnd == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Zero(&t, sizeof(RPC_NAT_STATUS));\r
+\r
+       CALL(hWnd, NcGetStatus(r, &t));\r
+\r
+       if (t.Online == false)\r
+       {\r
+               UniStrCpy(tmp, sizeof(tmp), _UU("NM_OFFLINE"));\r
+\r
+               Enable(hWnd, B_CONNECT);\r
+               Disable(hWnd, B_DISCONNECT);\r
+       }\r
+       else\r
+       {\r
+               if (t.Connected)\r
+               {\r
+                       UniFormat(tmp, sizeof(tmp), _UU("NM_CONNECTED"), t.Status.ServerName);\r
+               }\r
+               else\r
+               {\r
+                       if (t.LastError == ERR_NO_ERROR)\r
+                       {\r
+                               UniStrCpy(tmp, sizeof(tmp), _UU("NM_CONNECTING"));\r
+                       }\r
+                       else\r
+                       {\r
+                               UniFormat(tmp, sizeof(tmp), _UU("NM_CONNECT_ERROR"), t.LastError, _E(t.LastError));\r
+                       }\r
+               }\r
+               Disable(hWnd, B_CONNECT);\r
+               Enable(hWnd, B_DISCONNECT);\r
+       }\r
+\r
+       UniFormat(tmp2, sizeof(tmp2), _UU("NM_STATUS_TAG"), tmp);\r
+\r
+       SetText(hWnd, S_STATUS, tmp2);\r
+\r
+       FreeRpcNatStatus(&t);\r
+#endif\r
+}\r
+\r
+// メインダイアログプロシージャ\r
+UINT NmMainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+#if    0\r
+       SM_HUB *r = (SM_HUB *)param;\r
+       RPC_DUMMY dummy;\r
+       SM_SERVER sm;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               NmMainDlgInit(hWnd, r);\r
+\r
+               SetTimer(hWnd, 1, NM_REFRESH_TIME, NULL);\r
+\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case B_SETTING:\r
+                       // 接続設定\r
+                       NmEditClientConfig(hWnd, r);\r
+                       break;\r
+\r
+               case B_CONNECT:\r
+                       // 接続\r
+                       Zero(&dummy, sizeof(dummy));\r
+                       CALL(hWnd, NcOnline(r, &dummy));\r
+                       NmMainDlgRefresh(hWnd, r);\r
+                       break;\r
+\r
+               case B_DISCONNECT:\r
+                       // 切断\r
+                       Zero(&dummy, sizeof(dummy));\r
+                       CALL(hWnd, NcOffline(r, &dummy));\r
+                       NmMainDlgRefresh(hWnd, r);\r
+                       break;\r
+\r
+               case B_OPTION:\r
+                       // 動作設定\r
+                       NmEditVhOption(hWnd, r->Rpc);\r
+                       break;\r
+\r
+               case B_NAT:\r
+                       // NAT\r
+                       NmNat(hWnd, r);\r
+                       break;\r
+\r
+               case B_DHCP:\r
+                       // DHCP\r
+                       NmDhcp(hWnd, r);\r
+                       break;\r
+\r
+               case B_STATUS:\r
+                       // 状況\r
+                       Zero(&sm, sizeof(sm));\r
+                       sm.Rpc = r;\r
+                       SmStatusDlg(hWnd, &sm, NULL, true, true, _UU("NM_STATUS"), ICO_ROUTER,\r
+                               NULL, NmStatus);\r
+                       break;\r
+\r
+               case B_INFO:\r
+                       // 情報\r
+                       Zero(&sm, sizeof(sm));\r
+                       sm.Rpc = r;\r
+                       SmStatusDlg(hWnd, &sm, NULL, false, true, _UU("NM_INFO"), ICO_ROUTER,\r
+                               NULL, NmInfo);\r
+                       break;\r
+\r
+               case B_REFRESH:\r
+                       // 更新\r
+                       NmMainDlgRefresh(hWnd, r);\r
+                       break;\r
+\r
+               case B_PASSWORD:\r
+                       // パスワード変更\r
+                       NmChangePassword(hWnd, r);\r
+                       break;\r
+\r
+               case B_ABOUT:\r
+                       // バージョン情報\r
+                       About(hWnd, nm->Cedar, CEDAR_ROUTER_STR, BMP_SPLASH_ROUTER);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       KillTimer(hWnd, 1);\r
+\r
+                       if (IsEnable(hWnd, 0))\r
+                       {\r
+                               NmMainDlgRefresh(hWnd, r);\r
+                       }\r
+\r
+                       SetTimer(hWnd, 1, NM_REFRESH_TIME, NULL);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+#endif\r
+\r
+       return 0;\r
+}\r
+\r
+// メインダイアログ\r
+void NmMainDlg(RPC *r)\r
+{\r
+       // 引数チェック\r
+       if (r == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       Dialog(NULL, D_NM_MAIN, NmMainDlgProc, r);\r
+}\r
+\r
+// ログインダイアログ\r
+UINT NmLogin(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       NM_LOGIN *login = (NM_LOGIN *)param;\r
+       char tmp[MAX_SIZE];\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               FormatText(hWnd, S_TITLE, login->Hostname);\r
+               break;\r
+\r
+       case WM_COMMAND:\r
+               switch (wParam)\r
+               {\r
+               case IDOK:\r
+                       GetTxtA(hWnd, E_PASSWORD, tmp, sizeof(tmp));\r
+                       Hash(login->hashed_password, tmp, StrLen(tmp), true);\r
+                       EndDialog(hWnd, true);\r
+                       break;\r
+\r
+               case IDCANCEL:\r
+                       Close(hWnd);\r
+                       break;\r
+               }\r
+               break;\r
+\r
+       case WM_CLOSE:\r
+               EndDialog(hWnd, false);\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// 接続ダイアログ\r
+UINT NmConnectDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param)\r
+{\r
+       NM_CONNECT *t = (NM_CONNECT *)param;\r
+       RPC *rpc;\r
+       NM_LOGIN login;\r
+       UINT err;\r
+       // 引数チェック\r
+       if (hWnd == NULL)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       switch (msg)\r
+       {\r
+       case WM_INITDIALOG:\r
+               FormatText(hWnd, S_TITLE, t->Hostname);\r
+               SetTimer(hWnd, 1, 50, NULL);\r
+               break;\r
+\r
+       case WM_TIMER:\r
+               switch (wParam)\r
+               {\r
+               case 1:\r
+                       KillTimer(hWnd, 1);\r
+\r
+                       while (true)\r
+                       {\r
+                               bool flag = false;\r
+RETRY_PASSWORD:\r
+                               // パスワード入力ダイアログ\r
+                               Zero(&login, sizeof(login));\r
+                               login.Hostname = t->Hostname;\r
+                               login.Port = t->Port;\r
+                               Hash(login.hashed_password, "", 0, true);\r
+\r
+                               if (flag)\r
+                               {\r
+                                       if (Dialog(hWnd, D_NM_LOGIN, NmLogin, &login) == false)\r
+                                       {\r
+                                               EndDialog(hWnd, false);\r
+                                               break;\r
+                                       }\r
+                               }\r
+\r
+RETRY_CONNECT:\r
+                               Refresh(DlgItem(hWnd, S_TITLE));\r
+                               Refresh(hWnd);\r
+                               // 接続\r
+                               rpc = NatAdminConnect(nm->Cedar, t->Hostname, t->Port, login.hashed_password, &err);\r
+                               if (rpc != NULL)\r
+                               {\r
+                                       t->Rpc = rpc;\r
+                                       EndDialog(hWnd, true);\r
+                                       break;\r
+                               }\r
+\r
+                               // エラー\r
+                               if (err == ERR_ACCESS_DENIED || err == ERR_AUTH_FAILED)\r
+                               {\r
+                                       if (flag)\r
+                                       {\r
+                                               if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_RETRYCANCEL,\r
+                                                       _E(err)) == IDCANCEL)\r
+                                               {\r
+                                                       EndDialog(hWnd, false);\r
+                                                       break;\r
+                                               }\r
+                                       }\r
+                                       flag = true;\r
+                                       goto RETRY_PASSWORD;\r
+                               }\r
+                               else\r
+                               {\r
+                                       if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_RETRYCANCEL,\r
+                                               _E(err)) == IDCANCEL)\r
+                                       {\r
+                                               EndDialog(hWnd, false);\r
+                                               break;\r
+                                       }\r
+                                       goto RETRY_CONNECT;\r
+                               }\r
+                       }\r
+                       break;\r
+               }\r
+               break;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// User-mode NAT プログラムに接続する\r
+RPC *NmConnect(char *hostname, UINT port)\r
+{\r
+       NM_CONNECT t;\r
+       // 引数チェック\r
+       if (hostname == NULL || port == 0)\r
+       {\r
+               return NULL;\r
+       }\r
+\r
+       Zero(&t, sizeof(t));\r
+       t.Hostname = hostname;\r
+       t.Port = port;\r
+\r
+       Dialog(NULL, D_NM_CONNECT, NmConnectDlgProc, &t);\r
+\r
+       return t.Rpc;\r
+}\r
+\r
+// メイン処理\r
+void MainNM()\r
+{\r
+       UINT port;\r
+       char hostname[MAX_HOST_NAME_LEN + 1];\r
+       char *tmp =\r
+               RemoteDlg(NULL, NM_SETTING_REG_KEY, ICO_ROUTER,\r
+               _UU("NM_TITLE"), _UU("NM_CONNECT_TITLE"), NULL);\r
+       TOKEN_LIST *t;\r
+\r
+       Zero(hostname, sizeof(hostname));\r
+\r
+       if (tmp == NULL)\r
+       {\r
+               return;\r
+       }\r
+\r
+       t = ParseToken(tmp, ":");\r
+       port = DEFAULT_NAT_ADMIN_PORT;\r
+\r
+       if (t->NumTokens >= 2)\r
+       {\r
+               UINT i = ToInt(t->Token[1]);\r
+               if (i != 0)\r
+               {\r
+                       port = i;\r
+               }\r
+       }\r
+       if (t->NumTokens >= 1)\r
+       {\r
+               RPC *rpc;\r
+               StrCpy(hostname, sizeof(hostname), t->Token[0]);\r
+\r
+               // 接続\r
+               Trim(hostname);\r
+\r
+               if (StrLen(hostname) != 0)\r
+               {\r
+                       rpc = NmConnect(hostname, port);\r
+                       if (rpc != NULL)\r
+                       {\r
+                               // 接続した\r
+                               NmMainDlg(rpc);\r
+                               NatAdminDisconnect(rpc);\r
+                       }\r
+               }\r
+       }\r
+\r
+       FreeToken(t);\r
+\r
+       Free(tmp);\r
+}\r
+\r
+// 初期化\r
+void InitNM()\r
+{\r
+       if (nm != NULL)\r
+       {\r
+               // すでに初期化されている\r
+               return;\r
+       }\r
+\r
+       nm = ZeroMalloc(sizeof(NM));\r
+\r
+       InitWinUi(_UU("NM_TITLE"), _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));\r
+\r
+       nm->Cedar = NewCedar(NULL, NULL);\r
+\r
+       InitCM();\r
+       InitSM();\r
+}\r
+\r
+// 解放\r
+void FreeNM()\r
+{\r
+       if (nm == NULL)\r
+       {\r
+               // 初期化されていない\r
+               return;\r
+       }\r
+\r
+       FreeSM();\r
+       FreeCM();\r
+\r
+       ReleaseCedar(nm->Cedar);\r
+\r
+       FreeWinUi();\r
+\r
+       Free(nm);\r
+       nm = NULL;\r
+}\r
+\r
+// NM の実行\r
+void NMExec()\r
+{\r
+       InitNM();\r
+       MainNM();\r
+       FreeNM();\r
+}\r
+\r
+#endif\r
+\r