diff --git a/NetTunnelSDK/UserManager.cpp b/NetTunnelSDK/UserManager.cpp index ccd790b..e31a75b 100644 --- a/NetTunnelSDK/UserManager.cpp +++ b/NetTunnelSDK/UserManager.cpp @@ -141,6 +141,8 @@ int LocalWireGuardControl(bool isStart, bool setPrivateMode) { } if (GetCurrentNetShareMode() == ICS_SHARE_MODE) { + IP_INFO ipInfo; + // 获取 WireGuard 隧道网络网卡 Index if ((ret = GetInterfaceIfIndexByName(GetGlobalCfgInfo()->userCfg.userName, &ifWireGuardIndex)) != ERR_SUCCESS) { @@ -183,6 +185,13 @@ int LocalWireGuardControl(bool isStart, bool setPrivateMode) { return -ERR_NET_WIREGUARD_ICS; } + // 重设隧道 IP 地址 + GetIpV4InfoFromCIDR(GetGlobalCfgInfo()->userCfg.cliConfig.cliAddress, &ipInfo); + if ((ret = SetInterfaceIpAddressWMI(GetGlobalCfgInfo()->userCfg.userName, ipInfo.ip, ipInfo.netmask)) != ERR_SUCCESS) { + SPDLOG_ERROR(TEXT("Call SetInterfaceIpAddressWMI error: {0}"), ret); + return ret; + } + SPDLOG_INFO(TEXT("Net Share Service Work now on ICS mode: {0}"), GetGlobalCfgInfo()->userCfg.userName); } else if (GetCurrentNetShareMode() == NAT_SHARE_MODE) { IP_INFO ipInfo; @@ -408,6 +417,7 @@ int GetUserServerConfigure(const TCHAR *pUserName, const TCHAR *pToken, PUSER_SE int ret; PUSER_CONFIG pUser = &GetGlobalCfgInfo()->userCfg; PUSER_SERVER_CONFIG pUserCfg = &pUser->svrConfig; + TCHAR *pConvRet; #if USER_REAL_PLATFORM ProtocolRequest req; @@ -451,16 +461,16 @@ int GetUserServerConfigure(const TCHAR *pUserName, const TCHAR *pToken, PUSER_SE StringCbCopy(pUserCfg->svrAddress, MAX_IP_LEN, rsp.msgContent.svrAddress.c_str()); #else - req.vmIp = pToken; - ret = PlatformProtolPostMessage(GET_SERVERCFG_PATH, &req, &rsp); + req.extVmId = pToken; + ret = PlatformProtolPostMessage(GET_SERVERCFG_PATH, &req, &rsp); if (ret != ERR_SUCCESS) { return ret; } - ret = strtol(rsp.code.c_str(), nullptr, 10); + ret = strtol(rsp.code.c_str(), &pConvRet, 10); - if (ret != 0) { + if (ret != 0 || lstrlen(pConvRet) > 0) { SPDLOG_ERROR(TEXT("Server response error code: {0}"), ret); return -ERR_HTTP_SERVER_RSP; } diff --git a/NetTunnelSDK/include/protocol.h b/NetTunnelSDK/include/protocol.h index d756eb7..825fb7c 100644 --- a/NetTunnelSDK/include/protocol.h +++ b/NetTunnelSDK/include/protocol.h @@ -5,8 +5,8 @@ #if !USER_REAL_PLATFORM class PlatformReqServerCfgParms { public: - std::string vmIp; - AIGC_JSON_HELPER(vmIp) + std::string extVmId; + AIGC_JSON_HELPER(extVmId) }; class PlatformReqClientCfgParms { diff --git a/NetTunnelSDK/include/sccsdk.h b/NetTunnelSDK/include/sccsdk.h index d4fcef3..2758dc3 100644 --- a/NetTunnelSDK/include/sccsdk.h +++ b/NetTunnelSDK/include/sccsdk.h @@ -145,6 +145,27 @@ SCCSDK_API void __cdecl SetCurrentNetShareMode(NET_SHARE_MODE shareMode); */ SCCSDK_API int __cdecl GetAllNICInfo(PNIC_CONTENT *pInfo, int *pItemCounts); +/** + * @brief 设置网卡IP地址 + * @param pInterfaceName 网卡接口名称 + * @param pIpaddr 需要设置的 IP 地址 + * @param pNetmask 需要设置的子网掩码地址 + * @return 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_INPUT_PARAMS 输入参数错误 + * - -ERR_COM_INITIALIZE 初始化COM失败 + * - -ERR_CREATE_COMMOBJECT 创建 COM 对象失败 + * - -ERR_WMI_CONN_SVR 连接到 WMI 失败 + * - -ERR_WMI_SET_PROXY 设置 WMI 代理服务失败 + * - -ERR_WMI_QUERY 执行 WMI SQL 查询失败 + * - -ERR_WMI_EXEC_METHOD 执行 WMI 函数失败 + * - -ERR_ITEM_UNEXISTS 网卡不存在 + * - -ERR_MEMORY_STR 字符串转换失败 + * - ERR_SUCCESS 成功 + */ +SCCSDK_API int __cdecl SetInterfaceIpAddressWMI(const TCHAR *pInterfaceName, + const TCHAR *pIpaddr, + const TCHAR *pNetmask); + /** * @brief 获取当前 Internet 网卡名 * @param[out] pIfIndex 网卡索引 diff --git a/NetTunnelSDK/include/usrerr.h b/NetTunnelSDK/include/usrerr.h index 27ef62e..f9a15a8 100644 --- a/NetTunnelSDK/include/usrerr.h +++ b/NetTunnelSDK/include/usrerr.h @@ -60,10 +60,16 @@ enum USER_ERRNO { ERR_GET_IPFOWARDTBL = 300, ///< 获取系统 IP 转发表失败 ERR_CREATE_COMMOBJECT = 400, ///< 创建 COM 对象失败 ERR_CALL_COMMOBJECT, ///< 调用 COM 对象失败 + ERR_WMI_GET_COMMOBJECT, ///< 获取 WMI COM 对象失败 + ERR_WMI_CONN_SVR, ///< 连接到 WMI 失败 + ERR_WMI_SET_PROXY, ///< 设置 WMI 代理服务失败 + ERR_WMI_QUERY, ///< 执行 WMI SQL查询失败 + ERR_WMI_EXEC_METHOD, ///< 执行 WMI 函数失败 + ERR_COM_INITIALIZE, ///< 初始化COM失败 ERR_JSON_CREATE = 500, ///< 创建 JSON 对象失败 ERR_JSON_DECODE, ///< 从 JSON 反序列化对象失败 - ERR_HTTP_SERVER_RSP = 600, ///< HTTP 服务端返回错误 - ERR_HTTP_POST_DATA, ///< 发送 POST 请求失败 - ERR_NET_ADD_ROUTE, ///< 添加路由失败 - ERR_NET_REMOVE_ROUTE, ///< 删除路由失败 + ERR_HTTP_SERVER_RSP = 600, ///< HTTP 服务端返回错误 + ERR_HTTP_POST_DATA, ///< 发送 POST 请求失败 + ERR_NET_ADD_ROUTE, ///< 添加路由失败 + ERR_NET_REMOVE_ROUTE, ///< 删除路由失败 }; \ No newline at end of file diff --git a/NetTunnelSDK/network/network.cpp b/NetTunnelSDK/network/network.cpp index 8dd9254..e2c5fb2 100644 --- a/NetTunnelSDK/network/network.cpp +++ b/NetTunnelSDK/network/network.cpp @@ -15,9 +15,14 @@ #include #include +#include +#include +#include #pragma comment(lib, "Iphlpapi.lib") #pragma comment(lib, "Ws2_32.lib") +#pragma comment(lib, "comsuppwd.lib") +#pragma comment(lib, "wbemuuid.lib") static NIC_CONTENT g_NetAdapterInfo[NET_CARD_MAX]; @@ -1267,6 +1272,264 @@ int RemoveNATRule(const TCHAR *pInterfaceName) { return ERR_SUCCESS; } +/** + * @brief IPַ + * @param pInterfaceName ӿ + * @param pIpaddr Ҫõ IP ַ + * @param pNetmask Ҫõַ + * @return ɹ С0 ʧ @see USER_ERRNO + * - -ERR_INPUT_PARAMS + * - -ERR_COM_INITIALIZE ʼCOMʧ + * - -ERR_CREATE_COMMOBJECT COM ʧ + * - -ERR_WMI_CONN_SVR ӵ WMI ʧ + * - -ERR_WMI_SET_PROXY WMI ʧ + * - -ERR_WMI_QUERY ִ WMI SQL ѯʧ + * - -ERR_WMI_EXEC_METHOD ִ WMI ʧ + * - -ERR_ITEM_UNEXISTS + * - -ERR_MEMORY_STR ַתʧ + * - ERR_SUCCESS ɹ + */ +int SetInterfaceIpAddressWMI(const TCHAR *pInterfaceName, const TCHAR *pIpaddr, const TCHAR *pNetmask) { + int ret; + GUID guid; + IWbemLocator *pLoc = nullptr; + IWbemServices *pSvc = nullptr; + IEnumWbemClassObject *pEnum = nullptr; + IWbemClassObject *pObj = nullptr; + IWbemClassObject *pIfCfg = nullptr; + IWbemClassObject *params = nullptr; + IWbemClassObject *paramsInst = nullptr; + IWbemClassObject *pResult = nullptr; + VARIANT vPath; + VARIANT vtRet; + ULONG num = 0; + VARIANT paramVt; + SAFEARRAY *psa = nullptr; + long idx[] = {0}; + BSTR ip; + BSTR mask; + TCHAR wmiCmd[1024]; + + if (pInterfaceName == nullptr || lstrlen(pInterfaceName) == 0) { + SPDLOG_ERROR("Input pInterfaceName params error: {0}", pInterfaceName); + return -ERR_INPUT_PARAMS; + } + + if (pIpaddr == nullptr || lstrlen(pIpaddr) == 0) { + SPDLOG_ERROR("Input pIpaddr params error: {0}", pIpaddr); + return -ERR_INPUT_PARAMS; + } + + if (pNetmask == nullptr || lstrlen(pNetmask) == 0) { + SPDLOG_WARN("Input pNetmask params error: {0}", pNetmask); + return -ERR_INPUT_PARAMS; + } + + if ((ret = GetInterfaceGUIDByName(pInterfaceName, &guid)) != ERR_SUCCESS) { + SPDLOG_ERROR(TEXT("Get NetCard [{0}] GUID error: {1}"), pInterfaceName, ret); + return ret; + } + + // Step 1: Initialize COM. + HRESULT hr = CoInitialize(nullptr); + if (FAILED(hr)) { + SPDLOG_ERROR(TEXT("CoInitializeEx failed: {0}."), hr); + return -ERR_COM_INITIALIZE; + } + + // Step 2: Obtain the initial locator to WMI + hr = CoCreateInstance(CLSID_WbemLocator, + nullptr, + CLSCTX_INPROC_SERVER, + IID_IWbemLocator, + reinterpret_cast(&pLoc)); + if (FAILED(hr)) { + SPDLOG_ERROR(TEXT("CoCreateInstance WbemLocator failed: {0}."), hr); + return -ERR_CREATE_COMMOBJECT; + } + + // Step 3: Connect to the local root\cimv2 namespace and obtain pointer pSvc to make IWbemServices calls. + hr = pLoc->ConnectServer(_bstr_t("ROOT\\CIMV2"), nullptr, nullptr, nullptr, 0, nullptr, nullptr, &pSvc); + if (FAILED(hr)) { + SPDLOG_ERROR(TEXT("WMI ConnectServer failed: {0}."), hr); + pLoc->Release(); + return -ERR_WMI_CONN_SVR; + } + + // Step 4: Set security levels for the proxy + hr = CoSetProxyBlanket(pSvc, // Indicates the proxy to set + RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx + RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx + nullptr, // Server principal name + RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx + RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx + nullptr, // client identity + EOAC_NONE // proxy capabilities + ); + + if (FAILED(hr)) { + SPDLOG_ERROR(TEXT("WMI CoSetProxyBlanket failed: {0}."), hr); + pSvc->Release(); + pLoc->Release(); + return -ERR_WMI_SET_PROXY; + } + + memset(wmiCmd, 0, 1024); + StringCbPrintf(wmiCmd, + 1024, + TEXT("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE SettingID = " + "\"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\""), + guid.Data1, + guid.Data2, + guid.Data3, + guid.Data4[0], + guid.Data4[1], + guid.Data4[2], + guid.Data4[3], + guid.Data4[4], + guid.Data4[5], + guid.Data4[6], + guid.Data4[7]); + + hr = pSvc->ExecQuery(bstr_t("WQL"), + bstr_t(wmiCmd), + WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, + nullptr, + &pEnum); + if (FAILED(hr)) { + SPDLOG_ERROR(TEXT("WMI ExecQuery failed: {0}."), hr); + pSvc->Release(); + pLoc->Release(); + return -ERR_WMI_QUERY; + } + + // Get the adapter object. + hr = pEnum->Next(WBEM_INFINITE, 1, &pObj, &num); + if (FAILED(hr)) { + SPDLOG_ERROR(TEXT("Not found WBEM_INFINITE of {1}: {0}."), hr, pInterfaceName); + pEnum->Release(); + pSvc->Release(); + pLoc->Release(); + return -ERR_ITEM_UNEXISTS; + } + + if (num < 1) { + SPDLOG_ERROR(TEXT("WBEM_INFINITE of {1} is {2}: {0}."), hr, pInterfaceName, num); + pEnum->Release(); + pSvc->Release(); + pLoc->Release(); + pObj->Release(); + return -ERR_ITEM_UNEXISTS; + } + + VariantInit(&vPath); + hr = pObj->Get(L"__PATH", 0, &vPath, nullptr, nullptr); + + if (FAILED(hr)) { + SPDLOG_ERROR(TEXT("WMI GetObject Win32_NetworkAdapterConfiguration error: {0}."), hr); + pEnum->Release(); + pSvc->Release(); + pLoc->Release(); + pObj->Release(); + return -ERR_WMI_GET_COMMOBJECT; + } + + hr = pSvc->GetObject(_bstr_t(TEXT("Win32_NetworkAdapterConfiguration")), 0, nullptr, &pIfCfg, nullptr); + + if (FAILED(hr)) { + SPDLOG_ERROR(TEXT("WMI GetObject Win32_NetworkAdapterConfiguration error: {0}."), hr); + VariantClear(&vPath); + pEnum->Release(); + pSvc->Release(); + pLoc->Release(); + pObj->Release(); + return -ERR_WMI_GET_COMMOBJECT; + } + + pIfCfg->GetMethod(_bstr_t("EnableStatic"), 0, ¶ms, nullptr); + params->SpawnInstance(0, ¶msInst); + + psa = SafeArrayCreateVector(VT_BSTR, 0, 1); + ip = SysAllocString(_bstr_t(pIpaddr)); + idx[0] = 0; + + if (FAILED(SafeArrayPutElement(psa, idx, ip))) { + VariantClear(&vPath); + pEnum->Release(); + pSvc->Release(); + pLoc->Release(); + pObj->Release(); + paramsInst->Release(); + return -ERR_MEMORY_STR; + } + SysFreeString(ip); + + paramVt.vt = VT_ARRAY | VT_BSTR; + paramVt.parray = psa; + + hr = paramsInst->Put(L"IPAddress", 0, ¶mVt, 0); + SafeArrayDestroy(psa); + + psa = SafeArrayCreateVector(VT_BSTR, 0, 1); + mask = SysAllocString(_bstr_t(pNetmask)); + idx[0] = 0; + + if (FAILED(SafeArrayPutElement(psa, idx, mask))) { + VariantClear(&vPath); + pEnum->Release(); + pSvc->Release(); + pLoc->Release(); + pObj->Release(); + paramsInst->Release(); + return -ERR_MEMORY_STR; + } + SysFreeString(mask); + + paramVt.parray = psa; + hr = paramsInst->Put(L"SubnetMask", 0, ¶mVt, 0); + SafeArrayDestroy(psa); + + hr = pSvc->ExecMethod(vPath.bstrVal, _bstr_t(TEXT("EnableStatic")), 0, nullptr, paramsInst, &pResult, nullptr); + + if (FAILED(hr)) { + SPDLOG_ERROR(TEXT("WMI ExecMethod EnableStatic error: {0}."), hr); + VariantClear(&vPath); + pEnum->Release(); + pSvc->Release(); + pLoc->Release(); + pObj->Release(); + paramsInst->Release(); + return -ERR_WMI_EXEC_METHOD; + } + + VariantInit(&vtRet); + hr = pResult->Get(L"ReturnValue", 0, &vtRet, nullptr, nullptr); + + // Դ + VariantClear(&vPath); + pResult->Release(); + pEnum->Release(); + pSvc->Release(); + pLoc->Release(); + pObj->Release(); + paramsInst->Release(); + + if (SUCCEEDED(hr)) { + if (vtRet.uintVal == 0 || vtRet.uintVal == 1) { + VariantClear(&vtRet); + return ERR_SUCCESS; + } else { + SPDLOG_ERROR(TEXT("WMI ExecMethod EnableStatic ReturnValue error: {0}."), vtRet.uintVal); + VariantClear(&vtRet); + return -ERR_WMI_EXEC_METHOD; + } + } else { + SPDLOG_ERROR(TEXT("WMI ExecMethod EnableStatic error: {0}."), hr); + VariantClear(&vtRet); + return -ERR_WMI_EXEC_METHOD; + } +} + #if 0 int SetInterfaceIpAddress(const TCHAR *pInterfaceName, const TCHAR *pIpaddr, const TCHAR *pNetmask) { int ret; diff --git a/NetTunnelSDK/sdk/sccsdk.h b/NetTunnelSDK/sdk/sccsdk.h index e36634f..c600d00 100644 --- a/NetTunnelSDK/sdk/sccsdk.h +++ b/NetTunnelSDK/sdk/sccsdk.h @@ -145,6 +145,27 @@ SCCSDK_API void __cdecl SetCurrentNetShareMode(NET_SHARE_MODE shareMode); */ SCCSDK_API int __cdecl GetAllNICInfo(PNIC_CONTENT *pInfo, int *pItemCounts); +/** + * @brief IPַ + * @param pInterfaceName ӿ + * @param pIpaddr Ҫõ IP ַ + * @param pNetmask Ҫõַ + * @return ɹ С0 ʧ @see USER_ERRNO + * - -ERR_INPUT_PARAMS + * - -ERR_COM_INITIALIZE ʼCOMʧ + * - -ERR_CREATE_COMMOBJECT COM ʧ + * - -ERR_WMI_CONN_SVR ӵ WMI ʧ + * - -ERR_WMI_SET_PROXY WMI ʧ + * - -ERR_WMI_QUERY ִ WMI SQL ѯʧ + * - -ERR_WMI_EXEC_METHOD ִ WMI ʧ + * - -ERR_ITEM_UNEXISTS + * - -ERR_MEMORY_STR ַתʧ + * - ERR_SUCCESS ɹ + */ +SCCSDK_API int __cdecl SetInterfaceIpAddressWMI(const CHAR *pInterfaceName, + const CHAR *pIpaddr, + const CHAR *pNetmask); + /** * @brief ȡǰ Internet * @param[out] pIfIndex diff --git a/NetTunnelSDK/sdk/usrerr.h b/NetTunnelSDK/sdk/usrerr.h index bee39b3..c14a17d 100644 --- a/NetTunnelSDK/sdk/usrerr.h +++ b/NetTunnelSDK/sdk/usrerr.h @@ -60,10 +60,16 @@ enum USER_ERRNO { ERR_GET_IPFOWARDTBL = 300, ///< ȡϵͳ IP תʧ ERR_CREATE_COMMOBJECT = 400, ///< COM ʧ ERR_CALL_COMMOBJECT, ///< COM ʧ + ERR_WMI_GET_COMMOBJECT, ///< ȡ WMI COM ʧ + ERR_WMI_CONN_SVR, ///< ӵ WMI ʧ + ERR_WMI_SET_PROXY, ///< WMI ʧ + ERR_WMI_QUERY, ///< ִ WMI SQLѯʧ + ERR_WMI_EXEC_METHOD, ///< ִ WMI ʧ + ERR_COM_INITIALIZE, ///< ʼCOMʧ ERR_JSON_CREATE = 500, ///< JSON ʧ ERR_JSON_DECODE, ///< JSON лʧ - ERR_HTTP_SERVER_RSP = 600, ///< HTTP ˷ش - ERR_HTTP_POST_DATA, ///< POST ʧ - ERR_NET_ADD_ROUTE, ///< ·ʧ - ERR_NET_REMOVE_ROUTE, ///< ɾ·ʧ + ERR_HTTP_SERVER_RSP = 600, ///< HTTP ˷ش + ERR_HTTP_POST_DATA, ///< POST ʧ + ERR_NET_ADD_ROUTE, ///< ·ʧ + ERR_NET_REMOVE_ROUTE, ///< ɾ·ʧ }; diff --git a/NetTunnelServerApp/NetTunnelServerApp.cpp b/NetTunnelServerApp/NetTunnelServerApp.cpp index 1356080..c29ec46 100644 --- a/NetTunnelServerApp/NetTunnelServerApp.cpp +++ b/NetTunnelServerApp/NetTunnelServerApp.cpp @@ -17,7 +17,7 @@ int main() { EnableVerifySignature("sc-winvdisdk-efa9v12xwtz5eppr", "lh5r8sw6m9m416nm"); - if (ERR_SUCCESS != (ret = GetUserServerConfigure("tunnel_svr", "172.21.97.100", &pSvrCfg))) { + if (ERR_SUCCESS != (ret = GetUserServerConfigure("tunnel_svr", "7E9769CF-A5E6-41F3-8719-B81E8507C299", &pSvrCfg))) { wprintf(L"GetUserServerConfigure Error: %d\n", ret); return -2; } diff --git a/TestNetTunnelSDK/TestNetTunnelSDK.cpp b/TestNetTunnelSDK/TestNetTunnelSDK.cpp index c730913..6af3734 100644 --- a/TestNetTunnelSDK/TestNetTunnelSDK.cpp +++ b/TestNetTunnelSDK/TestNetTunnelSDK.cpp @@ -58,6 +58,11 @@ public: free(pInfo); } + TEST_METHOD(TestSetInterfaceIpAddressWMI) { + const int ret = SetInterfaceIpAddressWMI(TEXT("huangxin"), TEXT("192.168.100.100"), TEXT("255.255.0.0")); + Assert::AreEqual(RET_OK, ret); + } + #if 0 TEST_METHOD(TestSetInterfaceIpAddressFromCIDR) { Assert::AreEqual(RET_OK, SetInterfaceIpAddressFromCIDR(TEXT("wg_server"), TEXT("192.168.100.250/24")));