Files
netch/Redirector/DNSHandler.cpp
2021-08-01 13:22:02 +08:00

178 lines
3.3 KiB
C++

#include "DNSHandler.h"
#include "Utils.h"
void dns_freePacket(PDNSPKT i)
{
if (i)
{
if (i->Target)
{
delete[] i->Target;
}
if (i->Buffer)
{
delete[] i->Buffer;
}
if (i->Option)
{
delete i->Option;
}
delete i;
}
i = NULL;
}
DNSHandler::DNSHandler(string dnsHost, USHORT dnsPort)
{
this->dnsHost = dnsHost;
this->dnsPort = dnsPort;
}
BOOL DNSHandler::init()
{
this->Started = TRUE;
WaitForSingleObject(this->dnsLock, INFINITE);
for (size_t i = 0; i < 4; i++)
{
this->dnsLoop[i] = thread(&DNSHandler::Thread, this);
}
ReleaseMutex(this->dnsLock);
}
void DNSHandler::free()
{
if (this->dnsLock)
{
WaitForSingleObject(this->dnsLock, INFINITE);
}
this->Started = FALSE;
for (size_t i = 0; i < this->dnsLoop.size(); i++)
{
if (this->dnsLoop[i].joinable())
{
this->dnsLoop[i].join();
}
}
this->dnsLoop.clear();
auto size = this->dnsList.size();
for (size_t i = 0; i < size; i++)
{
dns_freePacket(this->dnsList.front());
}
if (this->dnsLock)
{
CloseHandle(this->dnsLock);
this->dnsLock = NULL;
}
}
void DNSHandler::Create(ENDPOINT_ID id, PBYTE target, ULONG targetLength, PCHAR buffer, ULONG bufferLength, PNF_UDP_OPTIONS option)
{
if (!this->Started)
{
return;
}
auto data = new DNSPKT();
data->ID = id;
data->Target = new BYTE[targetLength]();
data->TargetLength = targetLength;
data->Buffer = new CHAR[bufferLength]();
data->BufferLength = bufferLength;
data->Option = new NF_UDP_OPTIONS();
memcpy(data->Target, target, targetLength);
memcpy(data->Buffer, buffer, bufferLength);
memcpy(data->Option, option, sizeof(NF_UDP_OPTIONS));
WaitForSingleObject(this->dnsLock, INFINITE);
this->dnsList.emplace(data);
ReleaseMutex(this->dnsLock);
}
void DNSHandler::Thread()
{
while (this->Started && this->dnsLock)
{
switch (WaitForSingleObject(this->dnsLock, 10))
{
case WAIT_OBJECT_0:
this->Handle();
break;
default:
continue;
}
}
}
void DNSHandler::Handle()
{
SOCKADDR_IN addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(this->dnsPort);
if (!inet_pton(AF_INET, this->dnsHost.c_str(), &addr.sin_addr))
{
ReleaseMutex(this->dnsLock);
return;
}
auto data = this->dnsList.front();
this->dnsList.pop();
ReleaseMutex(this->dnsLock);
auto client = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (!client)
{
dns_freePacket(data);
printf("[Redirector][DNSHandler::Handle] Create socket failed: %d\n", WSAGetLastError());
return;
}
TIMEVAL tv;
tv.tv_sec = 4;
tv.tv_usec = 0;
FD_SET fds;
FD_ZERO(&fds);
FD_SET(client, &fds);
if (sendto(client, data->Buffer, data->BufferLength, 0, (PSOCKADDR)&addr, sizeof(SOCKADDR_IN)))
{
if (select(0, &fds, 0, 0, &tv))
{
CHAR buffer[1024];
auto length = recvfrom(client, buffer, sizeof(buffer), 0, NULL, NULL);
if (length)
{
nf_udpPostReceive(data->ID, data->Target, buffer, length, data->Option);
}
else
{
printf("[Redirector][DNSHandler::Handle] Receive failed: %d\n", WSAGetLastError());
}
}
else
{
puts("[Redirector][DNSHandler::Handle] Receive timed out");
}
}
else
{
printf("[Redirector][DNSHandler::Handle] Send failed: %d\n", WSAGetLastError());
}
closesocket(client);
dns_freePacket(data);
}