From 3424068993c12409450d05d508db62e023dde588 Mon Sep 17 00:00:00 2001 From: Fedotov Anton Date: Wed, 24 Nov 2021 03:00:27 +0300 Subject: [PATCH] Changes to the mechanics of obtaining data about network adapters --- client/3rd/AdpInfo/netadpinfo.h | 136 +++++---- client/3rd/AdpInfo/win_netadpinfo.cc | 410 +++++++-------------------- 2 files changed, 177 insertions(+), 369 deletions(-) diff --git a/client/3rd/AdpInfo/netadpinfo.h b/client/3rd/AdpInfo/netadpinfo.h index c90b87eb..dfc8ab3b 100644 --- a/client/3rd/AdpInfo/netadpinfo.h +++ b/client/3rd/AdpInfo/netadpinfo.h @@ -1,84 +1,102 @@ #pragma once -#include #include #include #include -//#include +#include + namespace adpinfo{ - -static bool is_string_equal(const std::string &lhs, const std::string &rhs){ - if (lhs.find(rhs) != std::string::npos) - return true; - return false; -} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//static bool is_string_equal(const std::string &lhs, const std::string &rhs){ +// if (lhs.find(rhs) != std::string::npos) +// return true; +// return false; +//} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// {false,""} - no error +// {true,"descr"} - error with description using RET_TYPE = std::tuple; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -typedef struct adapter{ - std::string name{}; - std::string mac{}; - std::list dns_address{}; - std::list> ip_mask_V4{}; - std::list gateWay{}; - std::string dhcp_server_adress{}; +//class Adapter{ +//private: +// std::string name{}; +// std::string descr{}; +// std::string current_ip_address_v4{}; +// std::string maskv4{}; +// std::vector dns_address{}; - std::string system_gateway{}; // default system gatewasy for ip 0.0.0.0 +//public: +// explicit Adapter() = default; +// ~Adapter() = default; - bool operator==(const adapter& rhs) { - if (!is_string_equal(name, rhs.name)) - return false; - if (!is_string_equal(mac, rhs.mac)) - return false; - if (dns_address != rhs.dns_address) - return false; - if (ip_mask_V4 != rhs.ip_mask_V4) - return false; - if (gateWay != rhs.gateWay) - return false; - if (!is_string_equal(dhcp_server_adress, rhs.dhcp_server_adress)) - return false; - if (!is_string_equal(system_gateway, rhs.system_gateway)) - return false; +// void set_name(std::string_view); +// std::string_view get_name()const; - return true; - } -}adapter; +// void set_description(std::string_view); +// std::string_view get_description()const; + +// void set_mac(std::string_view); +// std::string_view get_mac()const; + +//// bool operator==(const adapter& rhs) { +//// if (!is_string_equal(name, rhs.name)) +//// return false; +//// if (!is_string_equal(mac, rhs.mac)) +//// return false; +//// if (dns_address != rhs.dns_address) +//// return false; +//// return true; +//// } +//}adapter; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /* * The object uses for collect the information about active network adapters/interfaces - * NetAdpInfo adi; - * //Each call to the collect function fills - * //the _adapters array with information about active network connections (network address, gateways, ip addresses, etc.). - * adi.collect(); - * - * //We get the adapter that appeared after the penultimate call to the collect function - * adi.get_differents() - * - * //We get the adapter that appeared after the penultimate call to the collect function and - * //have a concrete system name - *get_adapter_info_by_name + * QString m_routeGateway; + QString m_vpnLocalAddress; + QString m_vpnGateway; */ class NetAdpInfo final{ + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + class Adapter{ + std::string name{}; + std::string descr{}; + std::string route{}; + std::string address{}; + std::string gateway{}; + public: + explicit Adapter() = default; + ~Adapter() = default; - bool init_error{false}; - std::vector_adapters{}; - adapter _adapter_in_use{}; + void set_name(std::string_view); + std::string_view get_name()const; + void set_description(std::string_view); + std::string_view get_description()const; + void set_route_gateway(std::string_view); + std::string_view get_route_gateway()const; + void set_local_address(std::string_view); + std::string_view get_local_address()const; + void set_local_gateway(std::string_view); + std::string_view get_local_gateway()const; + }; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + int16_t _index_of_adapter{}; + std::vector>_adapters{}; + + RET_TYPE collect_adapters_data(); public: - explicit NetAdpInfo(); - ~NetAdpInfo(); + explicit NetAdpInfo() = default; + ~NetAdpInfo() = default; + + RET_TYPE get_adapter_infor(std::string_view ); + std::string_view get_adapter_route_gateway()const; + std::string_view get_adapter_local_address()const; + std::string_view get_adapter_local_gateway()const; - //collect all adapter data - RET_TYPE collect(); - //return all adapter data - std::list get_adapters()const; - //get the diferent between the first call collect and the next call collect - adapter get_differents()const; - //get the adapter by name - adapter get_adapter_info_by_name(const std::string &)const; + //static std::string get_system_route(); }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -} +} //end namespace diff --git a/client/3rd/AdpInfo/win_netadpinfo.cc b/client/3rd/AdpInfo/win_netadpinfo.cc index f5365ad5..cf631c85 100644 --- a/client/3rd/AdpInfo/win_netadpinfo.cc +++ b/client/3rd/AdpInfo/win_netadpinfo.cc @@ -7,14 +7,14 @@ #include #include -#include -#include -#include +//#include +//#include +//#include #include #pragma comment(lib, "iphlpapi.lib") -#pragma comment(lib, "wbemuuid.lib") -#pragma comment(lib, "comsuppw.lib") +//#pragma comment(lib, "wbemuuid.lib") +//#pragma comment(lib, "comsuppw.lib") //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static std::string convert_wide_to_ansi(const std::wstring& widestring) { @@ -65,8 +65,8 @@ static std::string get_route_gateway() free(pIpForwardTable); return {"getIpForwardTable failed"}; } - const auto end = pIpForwardTable->dwNumEntries; - for (auto i = 0; i < end; i++) { + const DWORD end = pIpForwardTable->dwNumEntries; + for (DWORD i = 0; i < end; i++) { if (pIpForwardTable->table[i].dwForwardDest == 0) { // We have found the default gateway. IpAddr.S_un.S_addr = @@ -82,321 +82,111 @@ static std::string get_route_gateway() return route_gateway; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -namespace amnezia_wmi { +namespace adpinfo { -// prepare WMI object -static adpinfo::RET_TYPE prepare_WMI(CComPtr&pLoc, - CComPtr &pSvc, - CComPtr&pEnumerator){ - HRESULT result; - { - result = CoCreateInstance( - CLSID_WbemLocator, - 0, - CLSCTX_INPROC_SERVER, - IID_IWbemLocator, (LPVOID *)&pLoc); - if (FAILED(result)) - { - // TODO: add GetLastError description - return std::make_tuple(true, "CoCreateInstance failed"); - } - } +void NetAdpInfo::Adapter::set_name(std::string_view value){ + name = value; +} +std::string_view NetAdpInfo::Adapter::get_name()const{ - { - result = pLoc->ConnectServer( - _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace - NULL, // User name. NULL = current user - NULL, // User password. NULL = current - 0, // Locale. NULL indicates current - NULL, // Security flags. - 0, // Authority (for example, Kerberos) - 0, // Context object - &pSvc // pointer to IWbemServices proxy - ); - if (FAILED(result)) - { - // TODO: add GetLastError description - return std::make_tuple(true, "ConnectServer failed"); - } - } - { - result = CoSetProxyBlanket( - pSvc, // Indicates the proxy to set - RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx - RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx - NULL, // Server principal name - RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx - RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx - NULL, // client identity - EOAC_NONE // proxy capabilities - ); + return name; +} +void NetAdpInfo::Adapter::set_description(std::string_view value){ + descr = value; +} +std::string_view NetAdpInfo::Adapter::get_description()const{ + return descr; +} +void NetAdpInfo::Adapter::set_route_gateway(std::string_view value){ + route = value; +} +std::string_view NetAdpInfo::Adapter::get_route_gateway()const{ + return route; - if (FAILED(result)) - { - // TODO: add GetLastError description - return std::make_tuple(true, "CoSetProxyBlanket failed"); - } - } - { - result = pSvc->ExecQuery( - bstr_t("WQL"), - bstr_t("Select * from Win32_NetworkAdapterConfiguration WHERE IPEnabled = true"), - WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, - NULL, - &pEnumerator); - if (FAILED(result)) - { - // TODO: add GetLastError description - return std::make_tuple(true, "ExecQuery failed"); - } - } - return std::make_tuple(false,""); +} +void NetAdpInfo::Adapter::set_local_address(std::string_view value){ + address = value; +} +std::string_view NetAdpInfo::Adapter::get_local_address()const{ + return address; +} +void NetAdpInfo::Adapter::set_local_gateway(std::string_view value){ + gateway = value; +} +std::string_view NetAdpInfo::Adapter::get_local_gateway()const{ + return gateway; } -// get one WMI parametr from object -static std::string getValue(IWbemClassObject* pclsObj, const std::wstring& ParamName) { - VARIANT vtProp; - auto result = pclsObj->Get(ParamName.c_str(), 0, &vtProp, 0, 0); - if (FAILED(result)) { - VariantClear(&vtProp); - return {}; - } - if (vtProp.vt == VT_EMPTY || vtProp.vt == VT_NULL) { - VariantClear(&vtProp); - return {}; - } - const std::string &retValue = convert_wide_to_ansi(vtProp.bstrVal) ; - VariantClear(&vtProp); - return retValue; -} - -// get the array of WMI parametrs from object -static std::vectorgetValues(IWbemClassObject* pclsObj, const std::wstring& ParamName) { - VARIANT vtProp; - std::vector_values{}; - auto result = pclsObj->Get(ParamName.c_str(), 0, &vtProp, 0, 0); - if (FAILED(result)) { - VariantClear(&vtProp); - return std::vector(); - } - if (vtProp.vt == (VT_ARRAY | VT_BSTR)) { - SAFEARRAY* pSafeArray{ V_ARRAY(&vtProp) }; - BSTR elm; - long size = pSafeArray->rgsabound[0].cElements; - long i = 0; - for (i = 0; i < size; ++i) { - SafeArrayGetElement(pSafeArray, &i, (void*)&elm); - const std::wstring& widestring = elm; - const std::string& string_str = convert_wide_to_ansi(widestring); - _values.emplace_back(string_str); - } - VariantClear(&vtProp); - return _values; - } - else { - VariantClear(&vtProp); - return std::vector(); - } -} -} - -namespace adpinfo{ -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -NetAdpInfo::NetAdpInfo() -{ +RET_TYPE NetAdpInfo::collect_adapters_data(){ _adapters.clear(); - SetLastError(0); - HRESULT result = CoInitializeEx(0, COINIT_MULTITHREADED); - if (FAILED(result)) - { - init_error = true; - return; + std::vector buffer{}; + IP_ADAPTER_INFO *adapter_info{nullptr}; + DWORD result{ERROR_BUFFER_OVERFLOW}; + ULONG buffer_len = sizeof(IP_ADAPTER_INFO) * 3; + while (result == ERROR_BUFFER_OVERFLOW){ + buffer.resize(buffer_len); + adapter_info = reinterpret_cast(&buffer[0]); + result = GetAdaptersInfo(adapter_info, &buffer_len); + if (result == ERROR_NO_DATA){ + return {true, "GetAdaptersInfo return ERROR_NO_DATA"}; + } + }//end while + if (result != NO_ERROR){ + const std::string &error = "GetAdaptersInfo failed :" + std::to_string(result); + return {true, error}; } - - CoInitializeSecurity( - NULL, - -1, // COM authentication - NULL, // Authentication services - NULL, // Reserved - RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication - RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation - NULL, // Authentication info - EOAC_NONE, // Additional capabilities - NULL // Reserved - ); - // if (result != S_OK || result != RPC_E_TOO_LATE) - // { - // // TODO: add GetLastError description - // //_current_error = std::make_tuple(true, "CoInitializeSecurity failed"); - // //printf("%d\r\n", __LINE__); - // qDebug()<_tmp{std::make_shared()}; + _tmp->set_name(adapter_iterator->AdapterName); + _tmp->set_description(adapter_iterator->Description); + _tmp->set_local_address(adapter_iterator->IpAddressList.IpAddress.String); + _tmp->set_local_gateway(adapter_iterator->GatewayList.IpAddress.String); + _tmp->set_route_gateway(get_route_gateway()); + _adapters.emplace_back(_tmp); + adapter_iterator = adapter_iterator->Next; + } + return {false, ""}; } -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -NetAdpInfo::~NetAdpInfo() -{ - CoUninitialize(); -} -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -RET_TYPE NetAdpInfo::collect() -{ - if (init_error){ - return std::make_tuple(true,"Initial error"); - } - std::vector_adapters_next; - _adapters_next.clear(); - if (_adapters.size()>0){ - std::copy(_adapters.begin(), _adapters.end(), std::back_inserter(_adapters_next)); - _adapters.clear(); - } - CComPtr pLoc{nullptr}; - CComPtr pSvc{nullptr}; - CComPtr pEnumerator{nullptr}; - auto wmi_init {amnezia_wmi::prepare_WMI(pLoc, pSvc, pEnumerator)}; - if (std::get<0>(wmi_init)){ - return wmi_init; +RET_TYPE NetAdpInfo::get_adapter_infor(std::string_view _adapter_name){ + + _index_of_adapter = -1; + const auto result{collect_adapters_data()}; + if (std::get<0>(result) == true){ + _index_of_adapter = -1; + return result; } - CComPtr pclsObj{nullptr}; - ULONG uReturn = 0; - { - // get data from query - while (pEnumerator) - { - HRESULT result; - result = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); - if (FAILED(result)){ - break; - } - if (uReturn == 0) { - break; - } - - auto adap_name = amnezia_wmi::getValue(pclsObj, L"Description"); - auto adap_mac = amnezia_wmi::getValue(pclsObj, L"MACAddress"); - auto adap_dns = amnezia_wmi::getValues(pclsObj, L"DNSServerSearchOrder"); - auto adap_ips_address = amnezia_wmi::getValues(pclsObj, L"IPAddress"); - auto adap_ips_mask = amnezia_wmi::getValues(pclsObj, L"IPSubnet"); - auto adap_gateway = amnezia_wmi::getValues(pclsObj, L"DefaultIPGateway"); - auto adap_gate = amnezia_wmi::getValue(pclsObj, L"DHCPServer"); - { - adapter ainfo; - ainfo.name = adap_name; - ainfo.mac = adap_mac; - ainfo.dns_address = std::list(adap_dns.begin(), adap_dns.end()); - ainfo.gateWay = std::list(adap_gateway.begin(), adap_gateway.end()); - ainfo.dhcp_server_adress = adap_gate; - if (ainfo.gateWay.size() == 0) - ainfo.gateWay.push_back(get_route_gateway()); - - const auto ipv4_address_size = adap_ips_address.size(); - const auto ipv4_mask_size = adap_ips_mask.size(); - assert(ipv4_address_size == ipv4_mask_size); - for (auto i = 0; i < ipv4_address_size; ++i) { - ainfo.ip_mask_V4.emplace_back(std::make_tuple(adap_ips_address.at(i), adap_ips_mask.at(i))); - } - _adapters.emplace_back(ainfo); - } - pclsObj.Release(); - pclsObj = nullptr; + const int16_t &len = static_cast(_adapters.size()); + for (auto i = 0; i< len; ++i){ + auto adap_name = _adapters[i]->get_name(); + auto adap_desc = _adapters[i]->get_description(); + if (adap_name.find(_adapter_name) != std::string::npos || adap_desc.find(_adapter_name) != std::string::npos){ + _index_of_adapter = i; + return {false, ""}; } } - if (_adapters_next.size()>0){ - const auto newsize = _adapters.size(); - const auto oldsize = _adapters_next.size(); - if (newsize>oldsize){ - auto fv = _adapters; - for (int i = 0; i< newsize ;++i){ - if (i < oldsize){ - if (_adapters[i] == _adapters_next[i]){ - fv.erase(fv.begin()+i); - continue; - } - } - } - _adapter_in_use = *fv.begin(); - } - } - return std::make_tuple(false, ""); + return {true, "adapters no founded"}; +} + +std::string_view NetAdpInfo::get_adapter_route_gateway()const{ + if (_index_of_adapter < 0) + return "error adapter index"; + return _adapters.at(_index_of_adapter)->get_route_gateway(); +} +std::string_view NetAdpInfo::get_adapter_local_address()const{ + if (_index_of_adapter < 0) + return "error adapter index"; + return _adapters.at(_index_of_adapter)->get_local_address(); +} +std::string_view NetAdpInfo::get_adapter_local_gateway()const{ + if (_index_of_adapter < 0) + return "error adapter index"; + return _adapters.at(_index_of_adapter)->get_local_gateway(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -std::list NetAdpInfo::get_adapters()const { - return std::list(_adapters.begin(), _adapters.end()); -} +//std::string NetAdpInfo::get_system_route(){ +// return get_route_gateway(); +//} //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -adapter NetAdpInfo::get_differents()const{ - return _adapter_in_use; -} -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -adapter NetAdpInfo::get_adapter_info_by_name(const std::string &_adap_name)const{ - - adapter ainfo; - if (init_error){ - return ainfo; - } - CComPtr pLoc{nullptr}; - CComPtr pSvc{nullptr}; - CComPtr pEnumerator{nullptr}; - auto wmi_init = amnezia_wmi::prepare_WMI(pLoc, pSvc, pEnumerator); - if (std::get<0>(wmi_init)){ - return ainfo; - } - CComPtr pclsObj{nullptr}; - ULONG uReturn = 0; - { - // get data from query - while (pEnumerator) - { - HRESULT result; - result = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); - if (FAILED(result)){ - break; - } - if (uReturn == 0) { - break; - } - - auto adap_name = amnezia_wmi::getValue(pclsObj, L"Description"); // can take Caption - auto adap_mac = amnezia_wmi::getValue(pclsObj, L"MACAddress"); - auto adap_dns = amnezia_wmi::getValues(pclsObj, L"DNSServerSearchOrder"); - auto adap_ips_address = amnezia_wmi::getValues(pclsObj, L"IPAddress"); - auto adap_ips_mask = amnezia_wmi::getValues(pclsObj, L"IPSubnet"); - auto adap_gateway = amnezia_wmi::getValues(pclsObj, L"DefaultIPGateway"); - auto adap_gate = amnezia_wmi::getValue(pclsObj, L"DHCPServer"); - - { - adapter ainfoc; - ainfoc.system_gateway = get_route_gateway(); - ainfoc.name = adap_name; - ainfoc.mac = adap_mac; - ainfoc.dns_address = std::list(adap_dns.begin(), adap_dns.end()); - ainfoc.gateWay = std::list(adap_gateway.begin(), adap_gateway.end()); - ainfoc.dhcp_server_adress = adap_gate; - if (ainfoc.gateWay.size() == 0) - ainfoc.gateWay.push_back(get_route_gateway()); - - const auto ipv4_address_size = adap_ips_address.size(); - const auto ipv4_mask_size = adap_ips_mask.size(); - assert(ipv4_address_size == ipv4_mask_size); - for (auto i = 0; i < ipv4_address_size; ++i) { - ainfoc.ip_mask_V4.emplace_back(std::make_tuple(adap_ips_address.at(i), adap_ips_mask.at(i))); - } - qDebug()<<"Current adapter name is ["<