Big code refactoring #10

Merged
Sirherobrine23 merged 15 commits from code_refactoring into main 2024-03-15 04:08:27 +00:00
3 changed files with 205 additions and 342 deletions
Showing only changes of commit d7bb81dfbe - Show all commits

@ -37,19 +37,33 @@
const DEVPROPKEY devpkey_name = { { 0x65726957, 0x7547, 0x7261, { 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79 } }, DEVPROPID_FIRST_USABLE + 1 };
#define IFNAMSIZ MAX_ADAPTER_NAME - 1
// Create Wireguard adapter
static WIREGUARD_CREATE_ADAPTER_FUNC *WireGuardCreateAdapter;
// Open Wireguard adapter by name if exists
static WIREGUARD_OPEN_ADAPTER_FUNC *WireGuardOpenAdapter;
// Close Wireguard adapter
static WIREGUARD_CLOSE_ADAPTER_FUNC *WireGuardCloseAdapter;
// Get Wireguard adapter LUID
static WIREGUARD_GET_ADAPTER_LUID_FUNC *WireGuardGetAdapterLUID;
// Get running Wireguard driver version
static WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC *WireGuardGetRunningDriverVersion;
// Delete Wireguard driver if non exists adapters
static WIREGUARD_DELETE_DRIVER_FUNC *WireGuardDeleteDriver;
// Set logger for Wireguard adapter
static WIREGUARD_SET_LOGGER_FUNC *WireGuardSetLogger;
// Set adapter logging for Wireguard adapter
static WIREGUARD_SET_ADAPTER_LOGGING_FUNC *WireGuardSetAdapterLogging;
// Get adapter state for Wireguard adapter
static WIREGUARD_GET_ADAPTER_STATE_FUNC *WireGuardGetAdapterState;
// Set adapter state for Wireguard adapter
static WIREGUARD_SET_ADAPTER_STATE_FUNC *WireGuardSetAdapterState;
// Get Wireguard adapter configuration
static WIREGUARD_GET_CONFIGURATION_FUNC *WireGuardGetConfiguration;
// Set Wireguard adapter configuration
static WIREGUARD_SET_CONFIGURATION_FUNC *WireGuardSetConfiguration;
LPCWSTR WireguardAddonDescription = WireguardAddonDescription;
// Function to check if the current user has administrator privileges
bool IsRunAsAdmin() {
BOOL fRet = FALSE;
@ -92,90 +106,6 @@ std::string parseEndpoint(SOCKADDR_INET *input) {
return std::string(saddr).append(":").append(std::to_string(htons(input->Ipv4.sin_port)));
}
int parse_dns_retries() {
unsigned long ret;
char *retries = getenv("WG_ENDPOINT_RESOLUTION_RETRIES"), *end;
if (!retries) return 15;
if (!strcmp(retries, "infinity")) return -1;
ret = strtoul(retries, &end, 10);
if (*end || ret > INT_MAX) {
fprintf(stderr, "Unable to parse WG_ENDPOINT_RESOLUTION_RETRIES: `%s'\n", retries);
exit(1);
}
return (int)ret;
}
void insertEndpoint(SOCKADDR_INET *endpoint, std::string value) {
int ret, retries = parse_dns_retries();
char *begin, *end;
auto mmutable = strdup(value.c_str());
if (!mmutable) throw std::string("strdup");
if (!value.size()) {
free(mmutable);
throw std::string("Unable to parse empty endpoint");
}
if (mmutable[0] == '[') {
begin = &mmutable[1];
end = strchr(mmutable, ']');
if (!end) {
free(mmutable);
throw std::string("Unable to find matching brace of endpoint: ").append(value);
}
*end++ = '\0';
if (*end++ != ':' || !*end) {
free(mmutable);
throw std::string("Unable to find port of endpoint: ").append(value);
}
} else {
begin = mmutable;
end = strrchr(mmutable, ':');
if (!end || !*(end + 1)) {
free(mmutable);
throw std::string("Unable to find port of endpoint: ").append(value);
}
*end++ = '\0';
}
ADDRINFOA *resolved;
// #define min(a, b) ((a) < (b) ? (a) : (b))
for (unsigned int timeout = 1000000;; timeout = ((20000000) < (timeout * 6 / 5) ? (20000000) : (timeout * 6 / 5))) {
// ret = getaddrinfo(begin, end, &hints, &resolved);
ret = getaddrinfo(begin, end, NULL, &resolved);
if (!ret) break;
/* The set of return codes that are "permanent failures". All other possibilities are potentially transient.
*
* This is according to https://sourceware.org/glibc/wiki/NameResolver which states:
* "From the perspective of the application that calls getaddrinfo() it perhaps
* doesn't matter that much since EAI_FAIL, EAI_NONAME and EAI_NODATA are all
* permanent failure codes and the causes are all permanent failures in the
* sense that there is no point in retrying later."
*
* So this is what we do, except FreeBSD removed EAI_NODATA some time ago, so that's conditional.
*/
if (ret == EAI_NONAME || ret == EAI_FAIL ||
#ifdef EAI_NODATA
ret == EAI_NODATA ||
#endif
(retries >= 0 && !retries--)) {
free(mmutable);
throw std::string("Error code: ").append(std::to_string(ret));
}
std::this_thread::sleep_for(std::chrono::microseconds(timeout));
}
if ((resolved->ai_family == AF_INET && resolved->ai_addrlen == sizeof(SOCKADDR_IN))) memcpy(&endpoint->Ipv4, resolved->ai_addr, resolved->ai_addrlen);
else if (resolved->ai_family == AF_INET6 && resolved->ai_addrlen == sizeof(SOCKADDR_IN6)) memcpy(&endpoint->Ipv6, resolved->ai_addr, resolved->ai_addrlen);
else {
freeaddrinfo(resolved);
throw std::string("Neither IPv4 nor IPv6 address found: ").append(value);
}
freeaddrinfo(resolved);
free(mmutable);
}
std::string getErrorString(DWORD errorMessageID) {
if (errorMessageID == 0 || errorMessageID < 0) std::string("Error code: ").append(std::to_string(errorMessageID));
LPSTR messageBuffer = nullptr;
@ -211,7 +141,9 @@ std::string driveLoad(std::map<std::string, std::string> load) {
}
std::string getWireguardVersion() {
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardCreateAdapter(L"getWgVersion", L"Wireguard-tools.js", NULL);
// Create interface to get version
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardCreateAdapter(L"getWgVersion", WireguardAddonDescription, NULL);
WireGuardCloseAdapter(Adapter);
DWORD Version = WireGuardGetRunningDriverVersion();
if (Version == 0) {
auto statusErr = GetLastError();
@ -219,49 +151,25 @@ std::string getWireguardVersion() {
if (statusErr == ERROR_FILE_NOT_FOUND) return "Driver not loaded";
return std::string("Cannot get version drive, ").append(getErrorString(GetLastError()));
}
WireGuardCloseAdapter(Adapter);
return std::string("WireGuardNT v").append(std::to_string((Version >> 16) & 0xff)).append(".").append(std::to_string((Version >> 0) & 0xff));
return std::string("WireGuardNT v").append(std::to_string((Version >> 16) & 0xff)).append(".").append(std::to_string((Version >> 0) & 0xff)).append(".").append(std::to_string((Version >> 8) & 0xff));
}
void WireguardDevices::getInterfaces() {
// std::vector<std::string> arrayPrefix;
// arrayPrefix.push_back("ProtectedPrefix\\Administrators\\WireGuard\\");
// arrayPrefix.push_back("WireGuard\\");
// WIN32_FIND_DATA find_data;
// HANDLE find_handle;
// for (auto &preit : arrayPrefix) {
// int ret = 0;
// find_handle = FindFirstFile("\\\\.\\pipe\\*", &find_data);
// if (find_handle == INVALID_HANDLE_VALUE) continue;
// char *iface;
// do {
// if (strncmp(preit.c_str(), find_data.cFileName, strlen(preit.c_str()))) continue;
// iface = find_data.cFileName + strlen(preit.c_str());
// this->push_back(std::string("\\\\.\\pipe\\").append(preit).append(iface));
// } while (FindNextFile(find_handle, &find_data));
// FindClose(find_handle);
// if (ret < 0) throw std::string("Erro code: ").append(std::to_string(ret));
// }
HDEVINFO dev_info = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, L"SWD\\WireGuard", NULL, DIGCF_PRESENT, NULL, NULL, NULL);
if (dev_info == INVALID_HANDLE_VALUE) throw ("Cannot get devices");
for (DWORD i = 0;; ++i) {
DWORD buf_len;
WCHAR adapter_name[MAX_ADAPTER_NAME];
if (dev_info == INVALID_HANDLE_VALUE) throw std::string("Cannot get devices");
for (DWORD devIndex = 0;; ++devIndex) {
SP_DEVINFO_DATA dev_info_data;
dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
DEVPROPTYPE prop_type;
ULONG status, problem_code;
char *interface_name;
if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data)) {
if (!SetupDiEnumDeviceInfo(dev_info, devIndex, &dev_info_data)) {
if (GetLastError() == ERROR_NO_MORE_ITEMS) break;
continue;
}
DWORD buf_len; ULONG status, problem_code;
WCHAR adapter_name[MAX_ADAPTER_NAME];
char *interface_name;
DEVPROPTYPE prop_type;
if (!SetupDiGetDevicePropertyW(dev_info, &dev_info_data, &devpkey_name, &prop_type, (PBYTE)adapter_name, sizeof(adapter_name), NULL, 0) || prop_type != DEVPROP_TYPE_STRING) continue;
adapter_name[_countof(adapter_name) - 1] = L'0';
if (!adapter_name[0]) continue;
@ -281,28 +189,31 @@ void WireguardDevices::getInterfaces() {
SetupDiDestroyDeviceInfoList(dev_info);
}
/*
Delete wireguard interface
Current bug from Addon: Set interface down and not delete wireguard interface
*/
void WireguardDevices::deleteInterface(std::string wgName) {
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(wgName));
if (!Adapter) throw std::string("This interface not exists in Wireguard-Tools.js addon!");
if (!(WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_DOWN))) throw std::string(std::string("Failed to set down interface, ").append(getErrorString(GetLastError())));
if (!(WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_DOWN))) throw std::string("Failed to set down interface, ").append(getErrorString(GetLastError()));
WireGuardCloseAdapter(Adapter);
}
/**
* Change point from calloc or malloc
*
* T: to
* C: From
* Change point from calloc or malloc, T: from, C: to
*/
template <typename T, typename C> C* changePoint(T *x) {
// reinterpret_cast<WIREGUARD_ALLOWED_IP*>(((char*)x) + sizeof(WIREGUARD_PEER));
// std::cout << "Sizeof: " << sizeof(C) << ", " << typeid(T).name() << " -> " << typeid(C).name() << std::endl;
return reinterpret_cast<C*>(((char*)x) + sizeof(T));
}
void WireguardConfig::getWireguardConfig() {
if (this->name.length() == 0) throw std::string("Require interface name!");
else if (!(WireguardDevices().exist(this->name))) throw std::string("This interface not exists in Wireguard-Tools.js addon!");
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(this->name));
if (!Adapter) throw ("This interface not exists in Wireguard-Tools.js addon!");
if (!Adapter) throw std::string("This interface not exists in Wireguard-Tools.js addon!");
NET_LUID InterfaceLuid;
WireGuardGetAdapterLUID(Adapter, &InterfaceLuid);
this->interfaceAddress.GetInInterface(this->name);
@ -312,28 +223,27 @@ void WireguardConfig::getWireguardConfig() {
while (!(WireGuardGetConfiguration(Adapter, wg_iface, &buf_len))) {
free(wg_iface);
if (GetLastError() != ERROR_MORE_DATA) throw ((std::string("Failed get interface config, code: ")).append(std::to_string(GetLastError())));
if (GetLastError() != ERROR_MORE_DATA) throw std::string("Failed get interface config, code: ").append(std::to_string(GetLastError()));
wg_iface = (WIREGUARD_INTERFACE *)malloc(buf_len);
if (!wg_iface) throw std::string("Failed get interface config, ").append(std::to_string(-errno));
}
if (wg_iface->Flags & WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_PRIVATE_KEY) privateKey = wgKeys::toString(wg_iface->PrivateKey);
if (wg_iface->Flags & WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_PUBLIC_KEY) publicKey = wgKeys::toString(wg_iface->PublicKey);
portListen = 0;
if (wg_iface->Flags & WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_LISTEN_PORT) portListen = wg_iface->ListenPort;
if (wg_iface->Flags & WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_PRIVATE_KEY) this->privateKey = wgKeys::toString(wg_iface->PrivateKey);
if (wg_iface->Flags & WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_PUBLIC_KEY) this->publicKey = wgKeys::toString(wg_iface->PublicKey);
if (wg_iface->ListenPort > 0) this->portListen = wg_iface->ListenPort;
WIREGUARD_PEER *wg_peer = changePoint<WIREGUARD_INTERFACE, WIREGUARD_PEER>(wg_iface);
for (DWORD i = 0; i < wg_iface->PeersCount; i++) {
auto pubKey = wgKeys::toString(wg_peer->PublicKey);
Peer peerConfig;
peerConfig.txBytes = wg_peer->TxBytes;
peerConfig.rxBytes = wg_peer->RxBytes;
peerConfig.lastHandshake = (wg_peer->LastHandshake - 116444736000000000LL) / (100 / 1000);
if (wg_peer->Flags & WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_PRESHARED_KEY) peerConfig.presharedKey = wgKeys::toString(wg_peer->PresharedKey);
if (wg_peer->Flags & WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_ENDPOINT) peerConfig.endpoint = parseEndpoint(&wg_peer->Endpoint);
if (wg_peer->Flags & WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE) peerConfig.keepInterval = wg_peer->PersistentKeepalive;
if (wg_peer->LastHandshake > 0) peerConfig.lastHandshake = (wg_peer->LastHandshake - 116444736000000000LL) / (100 / 1000);
WIREGUARD_ALLOWED_IP* wg_aip = changePoint<WIREGUARD_PEER, WIREGUARD_ALLOWED_IP>(wg_peer);
for (DWORD __aip = 0; __aip < wg_peer->AllowedIPsCount; __aip++) {
@ -355,26 +265,28 @@ void WireguardConfig::getWireguardConfig() {
}
void WireguardConfig::setWireguardConfig() {
if (this->name.length() == 0) throw std::string("Require interface name!");
else if (this->name.length() > IFNAMSIZ) throw std::string("Interface name too long");
DWORD buf_len = sizeof(WIREGUARD_INTERFACE);
for (auto peer : this->Peers) {
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_PEER)) throw ("Buffer overflow");
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_PEER)) throw std::string("Buffer overflow");
buf_len += sizeof(WIREGUARD_PEER);
for (auto aip : peer.second.allowedIPs) {
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_ALLOWED_IP)) throw ("Buffer overflow");
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_ALLOWED_IP)) throw std::string("Buffer overflow");
buf_len += sizeof(WIREGUARD_ALLOWED_IP);
}
}
WIREGUARD_INTERFACE *wg_iface = reinterpret_cast<WIREGUARD_INTERFACE*>(calloc(1, buf_len));
if (!wg_iface) throw ("Cannot alloc buff");
if (!wg_iface) throw std::string("Cannot alloc buff");
wg_iface->PeersCount = 0;
wgKeys::stringToKey(wg_iface->PrivateKey, privateKey);
wgKeys::stringToKey(wg_iface->PrivateKey, this->privateKey);
wg_iface->Flags = WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_PRIVATE_KEY;
wg_iface->ListenPort = portListen;
if (portListen >= 0 && 65535 <= portListen) wg_iface->Flags = (WIREGUARD_INTERFACE_FLAG)(wg_iface->Flags|WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_LISTEN_PORT);
if (replacePeers) wg_iface->Flags = (WIREGUARD_INTERFACE_FLAG)(wg_iface->Flags|WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_REPLACE_PEERS);
wg_iface->ListenPort = this->portListen;
if (this->portListen >= 0) wg_iface->Flags = (WIREGUARD_INTERFACE_FLAG)(wg_iface->Flags|WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_LISTEN_PORT);
if (this->replacePeers) wg_iface->Flags = (WIREGUARD_INTERFACE_FLAG)(wg_iface->Flags|WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_REPLACE_PEERS);
WIREGUARD_ALLOWED_IP *wg_aip;
WIREGUARD_PEER *wg_peer = changePoint<WIREGUARD_INTERFACE, WIREGUARD_PEER>(wg_iface);
@ -398,7 +310,75 @@ void WireguardConfig::setWireguardConfig() {
if (peerConfig.keepInterval >= 0) wg_peer->Flags = (WIREGUARD_PEER_FLAG)(wg_peer->Flags|WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE);
if (peerConfig.endpoint.size() > 0) {
insertEndpoint(&wg_peer->Endpoint, peerConfig.endpoint.c_str());
int ret, retries = ([]() -> int {
unsigned long ret;
char *retries = getenv("WG_ENDPOINT_RESOLUTION_RETRIES"), *end;
if (!retries) return 15;
if (!strcmp(retries, "infinity")) return -1;
ret = strtoul(retries, &end, 10);
if (*end || ret > INT_MAX) {
fprintf(stderr, "Unable to parse WG_ENDPOINT_RESOLUTION_RETRIES: `%s'\n", retries);
exit(1);
}
return (int)ret;
})();
char *begin, *end;
auto mmutable = strdup(peerConfig.endpoint.c_str());
if (!mmutable) throw std::string("strdup");
if (!peerConfig.endpoint.size()) {
free(mmutable);
throw std::string("Unable to parse empty endpoint");
}
if (mmutable[0] == '[') {
begin = &mmutable[1];
end = strchr(mmutable, ']');
if (!end) {
free(mmutable);
throw std::string("Unable to find matching brace of endpoint: ").append(peerConfig.endpoint);
}
*end++ = '\0';
if (*end++ != ':' || !*end) {
free(mmutable);
throw std::string("Unable to find port of endpoint: ").append(peerConfig.endpoint);
}
} else {
begin = mmutable;
end = strrchr(mmutable, ':');
if (!end || !*(end + 1)) {
free(mmutable);
throw std::string("Unable to find port of endpoint: ").append(peerConfig.endpoint);
}
*end++ = '\0';
}
ADDRINFOA *resolved;
for (unsigned int timeout = 1000000;; timeout = ((20000000) < (timeout * 6 / 5) ? (20000000) : (timeout * 6 / 5))) {
// ret = getaddrinfo(begin, end, &hints, &resolved);
ret = getaddrinfo(begin, end, NULL, &resolved);
if (!ret) break;
if (ret == EAI_NONAME || ret == EAI_FAIL ||
#ifdef EAI_NODATA
ret == EAI_NODATA ||
#endif
(retries >= 0 && !retries--)) {
free(mmutable);
throw std::string("Error code: ").append(std::to_string(ret));
}
std::this_thread::sleep_for(std::chrono::microseconds(timeout));
}
if ((resolved->ai_family == AF_INET && resolved->ai_addrlen == sizeof(SOCKADDR_IN))) memcpy(&wg_peer->Endpoint.Ipv4, resolved->ai_addr, resolved->ai_addrlen);
else if (resolved->ai_family == AF_INET6 && resolved->ai_addrlen == sizeof(SOCKADDR_IN6)) memcpy(&wg_peer->Endpoint.Ipv6, resolved->ai_addr, resolved->ai_addrlen);
else {
freeaddrinfo(resolved);
throw std::string("Neither IPv4 nor IPv6 address found: ").append(peerConfig.endpoint);
}
freeaddrinfo(resolved);
free(mmutable);
wg_peer->Flags = (WIREGUARD_PEER_FLAG)(wg_peer->Flags|WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_ENDPOINT);
}
@ -420,38 +400,74 @@ void WireguardConfig::setWireguardConfig() {
}
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(this->name));
if (!Adapter) Adapter = WireGuardCreateAdapter(toLpcwstr(this->name), L"Wireguard-tools.js", NULL);
if (!Adapter) Adapter = WireGuardCreateAdapter(toLpcwstr(this->name), WireguardAddonDescription, NULL);
if (!Adapter) throw std::string("Failed to create adapter, ").append(getErrorString(GetLastError()));
else if (!WireGuardSetConfiguration(Adapter, reinterpret_cast<WIREGUARD_INTERFACE*>(wg_iface), buf_len)) {
auto status = WireGuardSetConfiguration(Adapter, reinterpret_cast<WIREGUARD_INTERFACE*>(wg_iface), buf_len) && WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_UP);
free(wg_iface);
if (!status) {
auto status = GetLastError();
WireGuardCloseAdapter(Adapter);
throw std::string("Failed to set interface config, ").append(getErrorString(status));
} else if (!WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_UP)) {
auto status = GetLastError();
WireGuardCloseAdapter(Adapter);
throw std::string("Failed to set interface up, ").append(getErrorString(status));
} else {
this->interfaceAddress.SetInInterface(this->name);
}
free(wg_iface);
this->interfaceAddress.SetInInterface(this->name);
}
void IpManeger::GetInInterface(std::string interfaceName) {
// Define the InterfaceLuid of the network interface you want to query
NET_IFINDEX ind;
NET_LUID InterfaceLuid;
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(interfaceName));
if (!Adapter) throw std::string("Cannot open wireguard adapter");
NET_LUID InterfaceLuid;
WireGuardGetAdapterLUID(Adapter, &InterfaceLuid);
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &ind) != NO_ERROR) throw std::string("Cannot get interface index");
ULONG bufferSize = 0; // Initial buffer size
// Call GetAdaptersAddresses to get the required buffer size
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, nullptr, &bufferSize) == ERROR_BUFFER_OVERFLOW) {
// Allocate memory for the buffer
PIP_ADAPTER_ADDRESSES addresses = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(bufferSize));
// Call GetAdaptersAddresses again with the allocated buffer
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, addresses, &bufferSize) == NO_ERROR) {
// Iterate through the list of adapters
for (PIP_ADAPTER_ADDRESSES adapter = addresses; adapter != nullptr; adapter = adapter->Next) {
// Check if the adapter matches the specified InterfaceLuid
if (memcmp(&adapter->Luid, &InterfaceLuid, sizeof(NET_LUID)) == 0) {
// Iterate through the list of IP addresses associated with the adapter
for (PIP_ADAPTER_UNICAST_ADDRESS address = adapter->FirstUnicastAddress; address != nullptr; address = address->Next) {
// Access the IP address in the address structure
sockaddr* sa = address->Address.lpSockaddr;
char ip[INET6_ADDRSTRLEN];
if (sa->sa_family == AF_INET) {
inet_ntop(AF_INET, &reinterpret_cast<sockaddr_in*>(sa)->sin_addr, ip, sizeof(ip));
} else if (sa->sa_family == AF_INET6) {
inet_ntop(AF_INET6, &reinterpret_cast<sockaddr_in6*>(sa)->sin6_addr, ip, sizeof(ip));
} else continue;
// Print or use the IP address as needed
this->addIPMask(std::string(ip).append("/").append(std::to_string(address->Address.iSockaddrLength)));
}
}
}
}
// Free the allocated buffer
free(addresses);
}
}
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createunicastipaddressentry
void IpManeger::SetInInterface(std::string interfaceName) {
if (this->size() == 0) return;
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(interfaceName));
if (!Adapter) throw std::string("Cannot open wireguard adapter");
NET_LUID InterfaceLuid;
WireGuardGetAdapterLUID(Adapter, &InterfaceLuid);
ULONG bufferSize = 0; // Initial buffer size
// Call GetAdaptersAddresses to get the required buffer size
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, nullptr, &bufferSize) == ERROR_BUFFER_OVERFLOW) {
// Allocate memory for the buffer
PIP_ADAPTER_ADDRESSES addresses = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(bufferSize));
// Call GetAdaptersAddresses again with the allocated buffer
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, addresses, &bufferSize) == NO_ERROR) {
// Iterate through the list of adapters
@ -469,8 +485,19 @@ void IpManeger::GetInInterface(std::string interfaceName) {
inet_ntop(AF_INET6, &reinterpret_cast<sockaddr_in6*>(sa)->sin6_addr, ip, sizeof(ip));
} else continue;
// Print or use the IP address as needed
this->addIPMask(std::string(ip).append("/").append(std::to_string(address->Address.iSockaddrLength)));
// Delete the IP address
MIB_UNICASTIPADDRESS_ROW row;
memset(&row, 0, sizeof(row));
WireGuardGetAdapterLUID(Adapter, &row.InterfaceLuid);
if (sa->sa_family == AF_INET) {
row.Address.si_family = AF_INET;
inet_pton(AF_INET, ip, &row.Address.Ipv4.sin_addr);
} else if (sa->sa_family == AF_INET6) {
row.Address.si_family = AF_INET6;
inet_pton(AF_INET6, ip, &row.Address.Ipv6.sin6_addr);
} else continue;
if (DeleteUnicastIpAddressEntry(&row) != NO_ERROR) throw std::string("Cannot delete IP address from interface");
}
}
}
@ -479,14 +506,25 @@ void IpManeger::GetInInterface(std::string interfaceName) {
// Free the allocated buffer
free(addresses);
}
}
void IpManeger::SetInInterface(std::string interfaceName) {
if (this->size() == 0) return;
NET_IFINDEX interfaceIndex;
NET_LUID InterfaceLuid;
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(interfaceName));
if (!Adapter) throw std::string("Cannot open wireguard adapter");
WireGuardGetAdapterLUID(Adapter, &InterfaceLuid);
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &interfaceIndex) != NO_ERROR) throw std::string("Cannot get interface index");
for (auto ip : this->getIpParsed()) {
MIB_UNICASTIPADDRESS_ROW row;
memset(&row, 0, sizeof(row));
memcpy(&row.InterfaceLuid, &InterfaceLuid, sizeof(NET_LUID));
row.DadState = NldsPreferred;
row.ValidLifetime = 0xffffffff;
row.PreferredLifetime = 0xffffffff;
row.OnLinkPrefixLength = ip.Mask;
if (ip.Proto == 4) {
row.Address.si_family = AF_INET;
inet_pton(AF_INET, ip.Address.c_str(), &row.Address.Ipv4.sin_addr);
} else if (ip.Proto == 6) {
row.Address.si_family = AF_INET6;
inet_pton(AF_INET6, ip.Address.c_str(), &row.Address.Ipv6.sin6_addr);
} else continue;
if (CreateUnicastIpAddressEntry(&row) != NO_ERROR) throw std::string("Cannot add IP address to interface");
}
}

@ -1,164 +0,0 @@
#include "wginterface.hh"
#include <vector>
#include <string>
#include <windows.h>
#include <iostream>
#include <comdef.h>
#include <Wbemidl.h>
#include <windows.h>
#include <ws2ipdef.h>
#include <ws2def.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <netioapi.h>
#include <iphlpapi.h>
#include <win/wireguard.h>
#pragma comment(lib, "wbemuuid.lib")
std::string convertWcharString(const wchar_t *wcStr) {
int MAXLEN = sizeof(wcStr);
static char *tx;
wcstombs(tx, wcStr, MAXLEN+1);
tx[MAXLEN+1] = 0;
return std::string(tx);
}
LPCWSTR toLpcwstr(std::string s) {
wchar_t* wString = new wchar_t[s.length()+1];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, wString, s.length()+1);
return wString;
}
void SetIPAddress(IWbemServices* pSvc, IWbemClassObject* pclsObj, const wchar_t* propertyName, const wchar_t* ip) {
VARIANT vtProp;
HRESULT hres = pclsObj->Get(propertyName, 0, &vtProp, 0, 0);
if (SUCCEEDED(hres)) {
vtProp.vt = VT_BSTR;
vtProp.bstrVal = SysAllocString(ip);
hres = pclsObj->Put(propertyName, 0, &vtProp, 0);
VariantClear(&vtProp);
if (FAILED(hres)) {
std::cerr << "Failed to set " << propertyName << ". Error code: " << hres << std::endl;
throw std::string("Failed to set ").append(convertWcharString(propertyName)).append(". Error code: ").append(std::to_string(hres));
}
}
}
void IpManeger::GetInInterface(std::string interfaceName) {
NET_LUID InterfaceLuid;
NET_IFINDEX ind;
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &ind) != NO_ERROR) throw std::string("Cannot get interface index");
IP_ADAPTER_INFO *pAdapterInfo;
ULONG ulOutBufLen;
DWORD dwRetVal;
pAdapterInfo = (IP_ADAPTER_INFO *)malloc( sizeof(IP_ADAPTER_INFO) );
ulOutBufLen = sizeof(IP_ADAPTER_INFO);
if (GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS) {
free (pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen);
}
if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) != ERROR_SUCCESS) throw std::string("GetAdaptersInfo call failed with ").append(std::to_string(dwRetVal));
PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
while (pAdapter) {
if (pAdapter->Index == ind) this->push_back(std::string(pAdapter->IpAddressList.IpAddress.String).append("/32"));
pAdapter = pAdapter->Next;
}
if (pAdapterInfo) free(pAdapterInfo);
}
void IpManeger::SetInInterface(std::string interfaceName) {
if (this->size() == 0) return;
HRESULT hres;
// Initialize COM
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres)) throw std::string("Failed to initialize COM library. Error code: ").append(std::to_string(hres));
// Initialize security
hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
if (FAILED(hres)) {
CoUninitialize();
throw std::string("Failed to initialize security. Error code: ").append(std::to_string(hres));
}
// Obtain the initial locator
IWbemLocator* pLoc = NULL;
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
if (FAILED(hres)) {
CoUninitialize();
throw std::string("Failed to create IWbemLocator object. Error code: ").append(std::to_string(hres));
}
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices* pSvc = NULL;
hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
if (FAILED(hres)) {
pLoc->Release();
CoUninitialize();
throw std::string("Failed to connect to ROOT\\CIMV2. Error code: ").append(std::to_string(hres));
}
// Set the security levels on the proxy
hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
if (FAILED(hres)) {
pSvc->Release();
pLoc->Release();
CoUninitialize();
throw std::string("Failed to set proxy blanket. Error code: ").append(std::to_string(hres));
}
// Define the IP addresses and subnet mask
const wchar_t* subnetMask = L"255.255.255.0";
const wchar_t* adapterDescription = L"Your Network Adapter Description";
// Construct the query
wchar_t query[256];
NET_IFINDEX ind;
if (ConvertInterfaceLuidToIndex(&InterfaceLuid, &ind) != NO_ERROR) throw std::string("Cannot get interface index");
swprintf(query, L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE InterfaceIndex = '%s'", ind);
// Execute the query to get the network adapter configuration
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(bstr_t("WQL"), bstr_t(query), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
if (FAILED(hres)) {
pSvc->Release();
pLoc->Release();
CoUninitialize();
throw std::string("Query failed. Error code: ").append(std::to_string(hres));
}
// Iterate over the query results
IWbemClassObject* pclsObj = NULL;
ULONG uReturn = 0;
while (pEnumerator) {
hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (uReturn == 0) break;
// Set each IP address
for (const auto &ip : this->getIpParsed()) SetIPAddress(pSvc, pclsObj, L"IPAddress", toLpcwstr(ip.Address));
// Set the subnet mask
SetIPAddress(pSvc, pclsObj, L"IPSubnet", subnetMask);
// Save changes
hres = pSvc->PutInstance(pclsObj, WBEM_FLAG_UPDATE_ONLY, NULL, NULL);
if (FAILED(hres)) throw std::string("Failed to save changes. Error code: ").append(std::to_string(hres));
pclsObj->Release();
}
// Cleanup
pSvc->Release();
pLoc->Release();
CoUninitialize();
}

@ -64,18 +64,7 @@ export interface SetConfig extends Config<SetPeer> {
replacePeers?: boolean;
};
const addon = (await loadAddon(path.resolve(__dirname, "../binding.yaml"))).wginterface.load_addon<{
/** Userspace support */
userspace?: {
/** Wireguard-go version */
driveVersion?: string;
createTunel(wgName: string): Promise<string>;
deleteTunel(wgName: string): Promise<void>;
checkTunel(wgName: string): Promise<boolean>;
listTunels(): Promise<string[]>;
};
/** Kernel wireguard version */
export const addon = (await loadAddon(path.resolve(__dirname, "../binding.yaml"))).wginterface.load_addon<{
driveVersion?: string;
deleteInterface(name: string): Promise<void>;
listDevices(): Promise<string[]>;