1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-11-22 09:29:52 +03:00

Cedar/Admin: Implement RPC methods to add/delete/list WireGuard keys

This commit is contained in:
Davide Beatrici 2020-09-01 01:27:01 +02:00
parent dd1eebdbed
commit 6115f1c713
10 changed files with 233 additions and 0 deletions

View File

@ -1509,6 +1509,9 @@ PACK *AdminDispatch(RPC *rpc, char *name, PACK *p)
DECLARE_RPC_EX("GetServerCipherList", RPC_STR, StGetServerCipherList, InRpcStr, OutRpcStr, FreeRpcStr) DECLARE_RPC_EX("GetServerCipherList", RPC_STR, StGetServerCipherList, InRpcStr, OutRpcStr, FreeRpcStr)
DECLARE_RPC_EX("GetServerCipher", RPC_STR, StGetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr) DECLARE_RPC_EX("GetServerCipher", RPC_STR, StGetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
DECLARE_RPC_EX("SetServerCipher", RPC_STR, StSetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr) DECLARE_RPC_EX("SetServerCipher", RPC_STR, StSetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
DECLARE_RPC_EX("AddWgk", RPC_WGK, StAddWgk, InRpcWgk, OutRpcWgk, FreeRpcWgk)
DECLARE_RPC_EX("DeleteWgk", RPC_WGK, StDeleteWgk, InRpcWgk, OutRpcWgk, FreeRpcWgk)
DECLARE_RPC_EX("EnumWgk", RPC_WGK, StEnumWgk, InRpcWgk, OutRpcWgk, FreeRpcWgk)
DECLARE_RPC("CreateHub", RPC_CREATE_HUB, StCreateHub, InRpcCreateHub, OutRpcCreateHub) DECLARE_RPC("CreateHub", RPC_CREATE_HUB, StCreateHub, InRpcCreateHub, OutRpcCreateHub)
DECLARE_RPC("SetHub", RPC_CREATE_HUB, StSetHub, InRpcCreateHub, OutRpcCreateHub) DECLARE_RPC("SetHub", RPC_CREATE_HUB, StSetHub, InRpcCreateHub, OutRpcCreateHub)
DECLARE_RPC("GetHub", RPC_CREATE_HUB, StGetHub, InRpcCreateHub, OutRpcCreateHub) DECLARE_RPC("GetHub", RPC_CREATE_HUB, StGetHub, InRpcCreateHub, OutRpcCreateHub)
@ -1693,6 +1696,9 @@ DECLARE_SC_EX("GetServerCert", RPC_KEY_PAIR, ScGetServerCert, InRpcKeyPair, OutR
DECLARE_SC_EX("GetServerCipherList", RPC_STR, ScGetServerCipherList, InRpcStr, OutRpcStr, FreeRpcStr) DECLARE_SC_EX("GetServerCipherList", RPC_STR, ScGetServerCipherList, InRpcStr, OutRpcStr, FreeRpcStr)
DECLARE_SC_EX("GetServerCipher", RPC_STR, ScGetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr) DECLARE_SC_EX("GetServerCipher", RPC_STR, ScGetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
DECLARE_SC_EX("SetServerCipher", RPC_STR, ScSetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr) DECLARE_SC_EX("SetServerCipher", RPC_STR, ScSetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
DECLARE_SC_EX("AddWgk", RPC_WGK, ScAddWgk, InRpcWgk, OutRpcWgk, FreeRpcWgk)
DECLARE_SC_EX("DeleteWgk", RPC_WGK, ScDeleteWgk, InRpcWgk, OutRpcWgk, FreeRpcWgk)
DECLARE_SC_EX("EnumWgk", RPC_WGK, ScEnumWgk, InRpcWgk, OutRpcWgk, FreeRpcWgk)
DECLARE_SC("CreateHub", RPC_CREATE_HUB, ScCreateHub, InRpcCreateHub, OutRpcCreateHub) DECLARE_SC("CreateHub", RPC_CREATE_HUB, ScCreateHub, InRpcCreateHub, OutRpcCreateHub)
DECLARE_SC("SetHub", RPC_CREATE_HUB, ScSetHub, InRpcCreateHub, OutRpcCreateHub) DECLARE_SC("SetHub", RPC_CREATE_HUB, ScSetHub, InRpcCreateHub, OutRpcCreateHub)
DECLARE_SC("GetHub", RPC_CREATE_HUB, ScGetHub, InRpcCreateHub, OutRpcCreateHub) DECLARE_SC("GetHub", RPC_CREATE_HUB, ScGetHub, InRpcCreateHub, OutRpcCreateHub)
@ -9503,6 +9509,144 @@ UINT StSetServerCert(ADMIN *a, RPC_KEY_PAIR *t)
return ERR_NO_ERROR; return ERR_NO_ERROR;
} }
// Add a WireGuard key to the allowed key list
UINT StAddWgk(ADMIN *a, RPC_WGK *t)
{
UINT ret = ERR_NO_ERROR;
SERVER *s = a->Server;
CEDAR *c = s->Cedar;
LIST *to_add;
SERVER_ADMIN_ONLY;
to_add = NewListFast(NULL);
LockList(c->WgkList);
{
UINT i;
for (i = 0; i < t->Num; ++i)
{
WGK *rpc_wgk = &t->Wgks[i];
WGK *wgk;
if (IsEmptyStr(rpc_wgk->Key))
{
ret = ERR_INVALID_PARAMETER;
break;
}
if (Search(c->WgkList, rpc_wgk) != NULL)
{
ret = ERR_OBJECT_EXISTS;
break;
}
wgk = Malloc(sizeof(WGK));
StrCpy(wgk->Key, sizeof(wgk->Key), rpc_wgk->Key);
StrCpy(wgk->Hub, sizeof(wgk->Hub), rpc_wgk->Hub);
StrCpy(wgk->User, sizeof(wgk->User), rpc_wgk->User);
Add(to_add, wgk);
}
for (i = 0; i < LIST_NUM(to_add); ++i)
{
WGK *wgk = LIST_DATA(to_add, i);
ret == ERR_NO_ERROR ? Add(c->WgkList, wgk) : Free(wgk);
}
}
UnlockList(c->WgkList);
if (ret == ERR_NO_ERROR)
{
ALog(a, NULL, "LA_ADD_WGK", LIST_NUM(to_add));
IncrementServerConfigRevision(a->Server);
}
ReleaseList(to_add);
return ret;
}
// Delete a WireGuard key from the allowed key list
UINT StDeleteWgk(ADMIN *a, RPC_WGK *t)
{
UINT ret = ERR_NO_ERROR;
SERVER *s = a->Server;
CEDAR *c = s->Cedar;
LIST *to_delete;
SERVER_ADMIN_ONLY;
to_delete = NewListFast(NULL);
LockList(c->WgkList);
{
UINT i;
for (i = 0; i < t->Num; ++i)
{
WGK *wgk = Search(c->WgkList, &t->Wgks[i]);
if (wgk == NULL)
{
ret = ERR_OBJECT_NOT_FOUND;
break;
}
Add(to_delete, wgk);
}
if (ret == ERR_NO_ERROR)
{
for (i = 0; i < LIST_NUM(to_delete); ++i)
{
WGK *wgk = LIST_DATA(to_delete, i);
Delete(c->WgkList, wgk);
Free(wgk);
}
}
}
UnlockList(c->WgkList);
if (ret == ERR_NO_ERROR)
{
ALog(a, NULL, "LA_DELETE_WGK", LIST_NUM(to_delete));
IncrementServerConfigRevision(a->Server);
}
ReleaseList(to_delete);
return ret;
}
// List the allowed WireGuard keys
UINT StEnumWgk(ADMIN *a, RPC_WGK *t)
{
SERVER *s = a->Server;
CEDAR *c = s->Cedar;
SERVER_ADMIN_ONLY;
LockList(c->WgkList);
{
UINT i;
t->Num = LIST_NUM(c->WgkList);
t->Wgks = Malloc(sizeof(WGK) * t->Num);
for (i = 0; i < t->Num; ++i)
{
WGK *wgk = LIST_DATA(c->WgkList, i);
WGK *rpc_wgk = &t->Wgks[i];
StrCpy(rpc_wgk->Key, sizeof(rpc_wgk->Key), wgk->Key);
StrCpy(rpc_wgk->Hub, sizeof(rpc_wgk->Hub), wgk->Hub);
StrCpy(rpc_wgk->User, sizeof(rpc_wgk->User), wgk->User);
}
}
UnlockList(c->WgkList);
return ERR_NO_ERROR;
}
// Get status of connection to cluster controller // Get status of connection to cluster controller
UINT StGetFarmConnectionStatus(ADMIN *a, RPC_FARM_CONNECTION_STATUS *t) UINT StGetFarmConnectionStatus(ADMIN *a, RPC_FARM_CONNECTION_STATUS *t)
{ {
@ -14465,6 +14609,64 @@ void FreeRpcKeyPair(RPC_KEY_PAIR *t)
FreeK(t->Key); FreeK(t->Key);
} }
// RPC_WGK
void InRpcWgk(RPC_WGK *t, PACK *p)
{
UINT i;
// Validate arguments
if (t == NULL || p == NULL)
{
return;
}
Zero(t, sizeof(RPC_WGK));
t->Num = PackGetIndexCount(p, "Key");
if (t->Num == 0)
{
return;
}
t->Wgks = ZeroMalloc(sizeof(WGK) * t->Num);
for (i = 0; i < t->Num; ++i)
{
WGK *wgk = &t->Wgks[i];
PackGetStrEx(p, "Key", wgk->Key, sizeof(wgk->Key), i);
PackGetStrEx(p, "Hub", wgk->Hub, sizeof(wgk->Hub), i);
PackGetStrEx(p, "User", wgk->User, sizeof(wgk->User), i);
}
}
void OutRpcWgk(PACK *p, RPC_WGK *t)
{
UINT i;
// Validate arguments
if (t == NULL || p == NULL)
{
return;
}
for (i = 0; i < t->Num; ++i)
{
WGK *wgk = &t->Wgks[i];
PackAddStrEx(p, "Key", wgk->Key, i, t->Num);
PackAddStrEx(p, "Hub", wgk->Hub, i, t->Num);
PackAddStrEx(p, "User", wgk->User, i, t->Num);
}
}
void FreeRpcWgk(RPC_WGK *t)
{
// Validate arguments
if (t == NULL)
{
return;
}
Free(t->Wgks);
}
// NODE_INFO // NODE_INFO
void InRpcNodeInfo(NODE_INFO *t, PACK *p) void InRpcNodeInfo(NODE_INFO *t, PACK *p)
{ {

View File

@ -226,6 +226,13 @@ struct RPC_KEY_PAIR
UINT Flag1; // Flag1 UINT Flag1; // Flag1
}; };
// WireGuard keys
struct RPC_WGK
{
UINT Num; // Number of keys
WGK *Wgks; // Keys
};
// HUB option // HUB option
struct RPC_HUB_OPTION struct RPC_HUB_OPTION
{ {
@ -989,6 +996,9 @@ UINT StGetServerCert(ADMIN *a, RPC_KEY_PAIR *t);
UINT StGetServerCipherList(ADMIN *a, RPC_STR *t); UINT StGetServerCipherList(ADMIN *a, RPC_STR *t);
UINT StGetServerCipher(ADMIN *a, RPC_STR *t); UINT StGetServerCipher(ADMIN *a, RPC_STR *t);
UINT StSetServerCipher(ADMIN *a, RPC_STR *t); UINT StSetServerCipher(ADMIN *a, RPC_STR *t);
UINT StAddWgk(ADMIN *a, RPC_WGK *t);
UINT StDeleteWgk(ADMIN *a, RPC_WGK *t);
UINT StEnumWgk(ADMIN *a, RPC_WGK *t);
UINT StCreateHub(ADMIN *a, RPC_CREATE_HUB *t); UINT StCreateHub(ADMIN *a, RPC_CREATE_HUB *t);
UINT StSetHub(ADMIN *a, RPC_CREATE_HUB *t); UINT StSetHub(ADMIN *a, RPC_CREATE_HUB *t);
UINT StGetHub(ADMIN *a, RPC_CREATE_HUB *t); UINT StGetHub(ADMIN *a, RPC_CREATE_HUB *t);
@ -1137,6 +1147,9 @@ UINT ScGetServerCert(RPC *r, RPC_KEY_PAIR *t);
UINT ScGetServerCipherList(RPC *r, RPC_STR *t); UINT ScGetServerCipherList(RPC *r, RPC_STR *t);
UINT ScGetServerCipher(RPC *r, RPC_STR *t); UINT ScGetServerCipher(RPC *r, RPC_STR *t);
UINT ScSetServerCipher(RPC *r, RPC_STR *t); UINT ScSetServerCipher(RPC *r, RPC_STR *t);
UINT ScAddWgk(RPC *r, RPC_WGK *t);
UINT ScDeleteWgk(RPC *r, RPC_WGK *t);
UINT ScEnumWgk(RPC *r, RPC_WGK *t);
UINT ScCreateHub(RPC *r, RPC_CREATE_HUB *t); UINT ScCreateHub(RPC *r, RPC_CREATE_HUB *t);
UINT ScSetHub(RPC *r, RPC_CREATE_HUB *t); UINT ScSetHub(RPC *r, RPC_CREATE_HUB *t);
UINT ScGetHub(RPC *r, RPC_CREATE_HUB *t); UINT ScGetHub(RPC *r, RPC_CREATE_HUB *t);
@ -1394,6 +1407,9 @@ void OutRpcMemInfo(PACK *p, MEMINFO *t);
void InRpcKeyPair(RPC_KEY_PAIR *t, PACK *p); void InRpcKeyPair(RPC_KEY_PAIR *t, PACK *p);
void OutRpcKeyPair(PACK *p, RPC_KEY_PAIR *t); void OutRpcKeyPair(PACK *p, RPC_KEY_PAIR *t);
void FreeRpcKeyPair(RPC_KEY_PAIR *t); void FreeRpcKeyPair(RPC_KEY_PAIR *t);
void InRpcWgk(RPC_WGK *t, PACK *p);
void OutRpcWgk(PACK *p, RPC_WGK *t);
void FreeRpcWgk(RPC_WGK *t);
void InRpcAddAccess(RPC_ADD_ACCESS *t, PACK *p); void InRpcAddAccess(RPC_ADD_ACCESS *t, PACK *p);
void OutRpcAddAccess(PACK *p, RPC_ADD_ACCESS *t); void OutRpcAddAccess(PACK *p, RPC_ADD_ACCESS *t);
void InRpcDeleteAccess(RPC_DELETE_ACCESS *t, PACK *p); void InRpcDeleteAccess(RPC_DELETE_ACCESS *t, PACK *p);

View File

@ -300,6 +300,7 @@ typedef struct RPC_ENUM_FARM_ITEM RPC_ENUM_FARM_ITEM;
typedef struct RPC_ENUM_FARM RPC_ENUM_FARM; typedef struct RPC_ENUM_FARM RPC_ENUM_FARM;
typedef struct RPC_FARM_CONNECTION_STATUS RPC_FARM_CONNECTION_STATUS; typedef struct RPC_FARM_CONNECTION_STATUS RPC_FARM_CONNECTION_STATUS;
typedef struct RPC_KEY_PAIR RPC_KEY_PAIR; typedef struct RPC_KEY_PAIR RPC_KEY_PAIR;
typedef struct RPC_WGK RPC_WGK;
typedef struct RPC_HUB_OPTION RPC_HUB_OPTION; typedef struct RPC_HUB_OPTION RPC_HUB_OPTION;
typedef struct RPC_RADIUS RPC_RADIUS; typedef struct RPC_RADIUS RPC_RADIUS;
typedef struct RPC_HUB RPC_HUB; typedef struct RPC_HUB RPC_HUB;

View File

@ -2028,6 +2028,8 @@ LA_SET_FARM_SETTING 群集设置变更完成。
LA_SET_SERVER_CERT 服务端证书设定完成。 LA_SET_SERVER_CERT 服务端证书设定完成。
LA_REGENERATE_SERVER_CERT 服务器证书再次生成。新 CN"%S" LA_REGENERATE_SERVER_CERT 服务器证书再次生成。新 CN"%S"
LA_SET_SERVER_CIPHER 服务端的新加密算法名设定完成。新加密算法为 "%S"。 LA_SET_SERVER_CIPHER 服务端的新加密算法名设定完成。新加密算法为 "%S"。
LA_ADD_WGK Added %u WireGuard key(s).
LA_DELETE_WGK Deleted %u WireGuard key(s).
LA_CREATE_HUB 已创建新虚拟 HUB "%S"。 LA_CREATE_HUB 已创建新虚拟 HUB "%S"。
LA_SET_HUB 已变更虚拟 HUB 设置。 LA_SET_HUB 已变更虚拟 HUB 设置。
LA_DELETE_HUB 已删除虚拟 HUB "%S"。 LA_DELETE_HUB 已删除虚拟 HUB "%S"。

View File

@ -2011,6 +2011,8 @@ LA_SET_FARM_SETTING The clustering setting has been changed.
LA_SET_SERVER_CERT The server certificates have been set. LA_SET_SERVER_CERT The server certificates have been set.
LA_REGENERATE_SERVER_CERT The server certificate has been re-generated. The new CN: "%S" LA_REGENERATE_SERVER_CERT The server certificate has been re-generated. The new CN: "%S"
LA_SET_SERVER_CIPHER A new encryption algorithm name for the server has been set. The new encryption algorithm name is "%S". LA_SET_SERVER_CIPHER A new encryption algorithm name for the server has been set. The new encryption algorithm name is "%S".
LA_ADD_WGK Added %u WireGuard key(s).
LA_DELETE_WGK Deleted %u WireGuard key(s).
LA_CREATE_HUB A new Virtual Hub "%S" has been created. LA_CREATE_HUB A new Virtual Hub "%S" has been created.
LA_SET_HUB The Virtual Hub setting has been changed. LA_SET_HUB The Virtual Hub setting has been changed.
LA_DELETE_HUB The Virtual Hub "%S" has been deleted. LA_DELETE_HUB The Virtual Hub "%S" has been deleted.

View File

@ -2015,6 +2015,8 @@ LA_SET_FARM_SETTING クラスタリング設定を変更しました。
LA_SET_SERVER_CERT サーバー証明書を設定しました。 LA_SET_SERVER_CERT サーバー証明書を設定しました。
LA_REGENERATE_SERVER_CERT サーバー証明書を再生成しました。新しい CN: "%S" LA_REGENERATE_SERVER_CERT サーバー証明書を再生成しました。新しい CN: "%S"
LA_SET_SERVER_CIPHER サーバーの新しい暗号化アルゴリズム名を設定しました。新しい暗号化アルゴリズム名は "%S" です。 LA_SET_SERVER_CIPHER サーバーの新しい暗号化アルゴリズム名を設定しました。新しい暗号化アルゴリズム名は "%S" です。
LA_ADD_WGK Added %u WireGuard key(s).
LA_DELETE_WGK Deleted %u WireGuard key(s).
LA_CREATE_HUB 新しい仮想 HUB "%S" を作成しました。 LA_CREATE_HUB 新しい仮想 HUB "%S" を作成しました。
LA_SET_HUB 仮想 HUB の設定を変更しました。 LA_SET_HUB 仮想 HUB の設定を変更しました。
LA_DELETE_HUB 仮想 HUB "%S" を削除しました。 LA_DELETE_HUB 仮想 HUB "%S" を削除しました。

View File

@ -1993,6 +1993,8 @@ LA_SET_FARM_SETTING 클러스터링 설정을 변경했습니다.
LA_SET_SERVER_CERT 서버 인증서를 설정했습니다. LA_SET_SERVER_CERT 서버 인증서를 설정했습니다.
LA_REGENERATE_SERVER_CERT 서버 인증서를 다시 생성했습니다. 새로운 CN:"%S" LA_REGENERATE_SERVER_CERT 서버 인증서를 다시 생성했습니다. 새로운 CN:"%S"
LA_SET_SERVER_CIPHER 서버의 새로운 암호화 알고리즘 명을 설정했습니다. 새로운 암호화 알고리즘 명은 "%S"입니다. LA_SET_SERVER_CIPHER 서버의 새로운 암호화 알고리즘 명을 설정했습니다. 새로운 암호화 알고리즘 명은 "%S"입니다.
LA_ADD_WGK Added %u WireGuard key(s).
LA_DELETE_WGK Deleted %u WireGuard key(s).
LA_CREATE_HUB 새로운 가상 HUB "%S"를 만들었습니다. LA_CREATE_HUB 새로운 가상 HUB "%S"를 만들었습니다.
LA_SET_HUB 가상 HUB의 설정을 변경했습니다. LA_SET_HUB 가상 HUB의 설정을 변경했습니다.
LA_DELETE_HUB 가상 HUB "%S"를 삭제했습니다. LA_DELETE_HUB 가상 HUB "%S"를 삭제했습니다.

View File

@ -2011,6 +2011,8 @@ LA_SET_FARM_SETTING The clustering setting has been changed.
LA_SET_SERVER_CERT The server certificates have been set. LA_SET_SERVER_CERT The server certificates have been set.
LA_REGENERATE_SERVER_CERT The server certificate has been re-generated. The new CN: "%S" LA_REGENERATE_SERVER_CERT The server certificate has been re-generated. The new CN: "%S"
LA_SET_SERVER_CIPHER A new encryption algorithm name for the server has been set. The new encryption algorithm name is "%S". LA_SET_SERVER_CIPHER A new encryption algorithm name for the server has been set. The new encryption algorithm name is "%S".
LA_ADD_WGK Added %u WireGuard key(s).
LA_DELETE_WGK Deleted %u WireGuard key(s).
LA_CREATE_HUB A new Virtual Hub "%S" has been created. LA_CREATE_HUB A new Virtual Hub "%S" has been created.
LA_SET_HUB The Virtual Hub setting has been changed. LA_SET_HUB The Virtual Hub setting has been changed.
LA_DELETE_HUB The Virtual Hub "%S" has been deleted. LA_DELETE_HUB The Virtual Hub "%S" has been deleted.

View File

@ -2011,6 +2011,8 @@ LA_SET_FARM_SETTING The clustering setting has been changed.
LA_SET_SERVER_CERT The server certificates have been set. LA_SET_SERVER_CERT The server certificates have been set.
LA_REGENERATE_SERVER_CERT The server certificate has been re-generated. The new CN: "%S" LA_REGENERATE_SERVER_CERT The server certificate has been re-generated. The new CN: "%S"
LA_SET_SERVER_CIPHER A new encryption algorithm name for the server has been set. The new encryption algorithm name is "%S". LA_SET_SERVER_CIPHER A new encryption algorithm name for the server has been set. The new encryption algorithm name is "%S".
LA_ADD_WGK Added %u WireGuard key(s).
LA_DELETE_WGK Deleted %u WireGuard key(s).
LA_CREATE_HUB A new Virtual Hub "%S" has been created. LA_CREATE_HUB A new Virtual Hub "%S" has been created.
LA_SET_HUB The Virtual Hub setting has been changed. LA_SET_HUB The Virtual Hub setting has been changed.
LA_DELETE_HUB The Virtual Hub "%S" has been deleted. LA_DELETE_HUB The Virtual Hub "%S" has been deleted.

View File

@ -2031,6 +2031,8 @@ LA_SET_FARM_SETTING 群集設置變更完成。
LA_SET_SERVER_CERT 服務端證書設定完成。 LA_SET_SERVER_CERT 服務端證書設定完成。
LA_REGENERATE_SERVER_CERT 伺服器憑證再次生成。新 CN"%S" LA_REGENERATE_SERVER_CERT 伺服器憑證再次生成。新 CN"%S"
LA_SET_SERVER_CIPHER 服務端的新加密演算法名設定完成。新加密演算法為 "%S"。 LA_SET_SERVER_CIPHER 服務端的新加密演算法名設定完成。新加密演算法為 "%S"。
LA_ADD_WGK Added %u WireGuard key(s).
LA_DELETE_WGK Deleted %u WireGuard key(s).
LA_CREATE_HUB 已創建新虛擬 HUB "%S"。 LA_CREATE_HUB 已創建新虛擬 HUB "%S"。
LA_SET_HUB 已變更虛擬 HUB 設置。 LA_SET_HUB 已變更虛擬 HUB 設置。
LA_DELETE_HUB 已刪除虛擬 HUB "%S"。 LA_DELETE_HUB 已刪除虛擬 HUB "%S"。