DEV9: Add internal DNS server

This commit is contained in:
TheLastRar 2021-05-10 19:50:14 +01:00 committed by refractionpcsx2
parent ca3b857f22
commit 24f97fd221
12 changed files with 744 additions and 2 deletions

View File

@ -355,6 +355,7 @@ set(pcsx2DEV9Sources
DEV9/ATA/ATA_Transfer.cpp
DEV9/ATA/HddCreate.cpp
DEV9/InternalServers/DHCP_Server.cpp
DEV9/InternalServers/DNS_Server.cpp
DEV9/PacketReader/IP/UDP/DHCP/DHCP_Options.cpp
DEV9/PacketReader/IP/UDP/DHCP/DHCP_Packet.cpp
DEV9/PacketReader/IP/UDP/DNS/DNS_Classes.cpp
@ -366,6 +367,7 @@ set(pcsx2DEV9Sources
DEV9/PacketReader/NetLib.cpp
DEV9/smap.cpp
DEV9/DEV9.cpp
DEV9/DEV9Config.cpp
DEV9/flash.cpp
DEV9/pcap_io.cpp
DEV9/net.cpp
@ -378,6 +380,7 @@ set(pcsx2DEV9Headers
DEV9/ATA/HddCreate.h
DEV9/DEV9.h
DEV9/InternalServers/DHCP_Server.cpp
DEV9/InternalServers/DNS_Server.h
DEV9/net.h
DEV9/PacketReader/IP/UDP/DHCP/DHCP_Options.h
DEV9/PacketReader/IP/UDP/DHCP/DHCP_Packet.h

View File

@ -15,3 +15,6 @@
void SaveConf();
void LoadConf();
void SaveDnsHosts();
void LoadDnsHosts();

View File

@ -55,6 +55,14 @@ bool rx_fifo_can_rx();
#define HDD_MIN_GB 40
#define HDD_MAX_GB 120
struct ConfigHost
{
std::string Url;
std::string Desc;
u8 Address[4];
bool Enabled;
};
struct ConfigDEV9
{
char Eth[256];
@ -69,6 +77,7 @@ struct ConfigDEV9
int AutoGateway;
int AutoDNS1;
int AutoDNS2;
std::vector<ConfigHost> EthHosts;
#ifdef _WIN32
wchar_t Hdd[256];
#else

114
pcsx2/DEV9/DEV9Config.cpp Normal file
View File

@ -0,0 +1,114 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "ghc/filesystem.h"
#include <wx/fileconf.h>
#include "DEV9.h"
#include "gui/AppConfig.h"
#include "common/IniInterface.h"
#ifdef _WIN32
#include "ws2tcpip.h"
#elif defined(__POSIX__)
#include <arpa/inet.h>
#endif
void SaveDnsHosts()
{
std::unique_ptr<wxFileConfig> hini(OpenFileConfig(GetSettingsFolder().Combine(wxString("DEV9Hosts.ini")).GetFullPath()));
IniSaver ini((wxConfigBase*)hini.get());
for (size_t i = 0; i < config.EthHosts.size(); i++)
{
std::wstring groupName(L"Host" + std::to_wstring(i));
ScopedIniGroup iniEntry(ini, groupName);
ConfigHost entry = config.EthHosts[i];
wxString url(entry.Url);
ini.Entry(L"Url", url);
//TODO UTF8(?)
wxString desc(entry.Desc);
ini.Entry(L"Desc", desc);
char addrBuff[INET_ADDRSTRLEN];
inet_ntop(AF_INET, entry.Address, addrBuff, INET_ADDRSTRLEN);
wxString address(addrBuff);
ini.Entry(L"Address", address);
ini.Entry(L"Enabled", entry.Enabled);
}
ini.Flush();
}
void LoadDnsHosts()
{
wxFileName iniPath = GetSettingsFolder().Combine(wxString("DEV9Hosts.ini"));
config.EthHosts.clear();
//If no file exists, create one to provice an example config
if (!iniPath.FileExists())
{
//Load Default settings
ConfigHost exampleHost;
exampleHost.Url = "www.example.com";
exampleHost.Desc = "Set DNS to 192.0.2.1 to use this host list";
memset(exampleHost.Address, 0, 4);
exampleHost.Enabled = false;
config.EthHosts.push_back(exampleHost);
SaveDnsHosts();
return;
}
std::unique_ptr<wxFileConfig> hini(OpenFileConfig(iniPath.GetFullPath()));
IniLoader ini((wxConfigBase*)hini.get());
int i = 0;
while (true)
{
std::wstring groupName(L"Host" + std::to_wstring(i));
ScopedIniGroup iniEntry(ini, groupName);
wxString tmp = wxEmptyString;
ini.Entry(L"Url", tmp, wxEmptyString);
//An empty url means we tried to read beyond end of the host list
if (tmp.IsEmpty())
break;
ConfigHost entry;
entry.Url = tmp.ToUTF8();
ini.Entry(L"Desc", tmp, wxEmptyString);
entry.Desc = tmp.ToUTF8();
ini.Entry(L"Address", tmp, L"0.0.0.0");
int ret = inet_pton(AF_INET, tmp.ToUTF8(), entry.Address);
//Only check Enabled if valid ip
if (ret != 1)
{
memset(entry.Address, 0, 4);
entry.Enabled = false;
}
else
ini.Entry(L"Enabled", entry.Enabled, false);
if (entry.Enabled)
Console.WriteLn("DEV9: Host entry %i: url %s mapped to %s", i, entry.Url.c_str(), tmp.ToStdString().c_str());
config.EthHosts.push_back(entry);
i++;
}
}

View File

@ -0,0 +1,435 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include <chrono>
#include <thread>
#ifdef _WIN32
#include <ws2tcpip.h>
#elif defined(__POSIX__)
//Note that getaddrinfo_a() exists which allows asynchronous operation
//however, that function is not standard POSIX, and is instead part of glibc
//So we will run with getaddrinfo() in a thread ourself
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#endif
#include "DNS_Server.h"
#include "DEV9/PacketReader/IP/UDP/UDP_Packet.h"
#include "DEV9/PacketReader/IP/UDP/DNS/DNS_Packet.h"
#include "DEV9/DEV9.h"
using namespace PacketReader;
using namespace PacketReader::IP;
using namespace PacketReader::IP::UDP;
using namespace PacketReader::IP::UDP::DNS;
namespace InternalServers
{
DNS_Server::DNS_State::DNS_State(int count, std::vector<std::string> dnsQuestions, DNS_Packet* dnsPacket, u16 port)
{
dns = dnsPacket;
counter.store(count);
questions = dnsQuestions;
clientPort = port;
//Prefill unordered_map, allowing use to modify it from seperate threads
//See https://en.cppreference.com/w/cpp/container#Thread_safety
//Different elements in the same container can be modified concurrently by different threads
for (size_t i = 0; i < dnsQuestions.size(); i++)
answers[dnsQuestions[i]] = {0};
}
int DNS_Server::DNS_State::AddAnswer(const std::string& answer, IP_Address address)
{
answers[answer] = address;
return --counter;
}
int DNS_Server::DNS_State::AddNoAnswer(const std::string& answer)
{
return --counter;
}
std::unordered_map<std::string, IP_Address> DNS_Server::DNS_State::GetAnswers()
{
return answers;
}
DNS_Server::DNS_Server(std::function<void()> receivedcallback)
: callback{receivedcallback}
{
#ifdef _WIN32
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData{0};
const int err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
Console.Error("DEV9: WSAStartup failed with error: %d\n", err);
else
wsa_init = true;
#endif
}
//We remap 127.0.0.1 to the PC's IP address
//We specificly use the address assigned to
//the adapter we are using
#ifdef _WIN32
void DNS_Server::Init(PIP_ADAPTER_ADDRESSES adapter)
#elif defined(__POSIX__)
void DNS_Server::Init(ifaddrs* adapter)
#endif
{
localhostIP = {127, 0, 0, 1};
//Find IPv4 Address
#ifdef _WIN32
PIP_ADAPTER_UNICAST_ADDRESS address = nullptr;
if (adapter != nullptr)
{
PIP_ADAPTER_ADDRESSES info = (PIP_ADAPTER_ADDRESSES)adapter;
address = info->FirstUnicastAddress;
while (address != nullptr && address->Address.lpSockaddr->sa_family != AF_INET)
address = address->Next;
}
if (address != nullptr)
{
sockaddr_in* sockaddr = (sockaddr_in*)address->Address.lpSockaddr;
localhostIP = *(IP_Address*)&sockaddr->sin_addr;
}
else
Console.Error("DEV9: Failed To Get Adapter IP");
#elif defined(__POSIX__)
sockaddr* address = nullptr;
if (adapter != nullptr)
{
ifaddrs* info = (ifaddrs*)adapter;
if (info->ifa_addr != nullptr && info->ifa_addr->sa_family == AF_INET)
address = info->ifa_addr;
}
if (address != nullptr)
{
sockaddr_in* sockaddr = (sockaddr_in*)address;
localhostIP = *(IP_Address*)&sockaddr->sin_addr;
}
else
Console.Error("DEV9: Failed To Get Adapter IP");
#endif
LoadHostList();
}
void DNS_Server::LoadHostList()
{
hosts.clear();
for (size_t i = 0; i < config.EthHosts.size(); i++)
{
ConfigHost entry = config.EthHosts[i];
if (entry.Enabled)
hosts.insert_or_assign(entry.Url, *(IP_Address*)entry.Address);
}
}
UDP_Packet* DNS_Server::Recv()
{
UDP_Packet* retPay;
if (dnsQueue.Dequeue(&retPay))
{
outstandingQueries--;
return retPay;
}
return nullptr;
}
bool DNS_Server::Send(UDP_Packet* payload)
{
PayloadPtr* udpPayload = static_cast<PayloadPtr*>(payload->GetPayload());
DNS_Packet dns(udpPayload->data, udpPayload->GetLength());
if (dns.GetOpCode() == (u8)DNS_OPCode::Query && dns.questions.size() > 0 && dns.GetQR() == false)
{
std::vector<std::string> reqs;
for (size_t i = 0; i < dns.questions.size(); i++)
{
DNS_QuestionEntry q = dns.questions[i];
if (q.entryType == 1 && q.entryClass == 1)
reqs.push_back(q.name);
else
Console.Error("DEV9: Unexpected question type of class, T: %d C: %d", q.entryType, q.entryClass);
}
if (reqs.size() == 0)
return true;
if (dns.GetTC() == true)
{
Console.Error("DEV9: Truncated DNS packet Not Supported");
return true;
}
DNS_Packet* ret = new DNS_Packet();
ret->id = dns.id; //TODO, drop duplicate requests based on ID
ret->SetQR(true);
ret->SetOpCode((u8)DNS_OPCode::Query);
ret->SetAA(false);
ret->SetTC(false);
ret->SetRD(true);
ret->SetRA(true);
ret->SetAD(false);
ret->SetCD(false);
ret->SetRCode((u8)DNS_RCode::NoError);
//Counts
ret->questions = dns.questions;
DNS_State* state = new DNS_State(reqs.size(), reqs, ret, payload->sourcePort);
outstandingQueries++;
for (size_t i = 0; i < reqs.size(); i++)
{
if (CheckHostList(reqs[i], state))
continue;
GetHost(reqs[i], state);
}
return true;
}
else
{
Console.Error("DEV9: Unexpected DNS OPCode, Code: %s", dns.GetOpCode());
return true;
}
}
bool DNS_Server::CheckHostList(std::string url, DNS_State* state)
{
std::transform(url.begin(), url.end(), url.begin(),
[](unsigned char c) { return std::tolower(c); });
auto f = hosts.find(url);
if (f != hosts.end())
{
const int remaining = state->AddAnswer(url, hosts[url]);
Console.WriteLn("DEV9: DNS: %s found in hosts", url.c_str());
if (remaining == 0)
FinaliseDNS(state);
return true;
}
return false;
}
void DNS_Server::FinaliseDNS(DNS_State* state)
{
DNS_Packet* retPay = state->dns;
std::vector<std::string> reqs = state->questions;
std::unordered_map<std::string, IP_Address> answers = state->GetAnswers();
for (size_t i = 0; i < reqs.size(); i++)
{
IP_Address ans = answers[reqs[i]];
if (ans.integer != 0)
{
//TODO, might not be effective on pcap
const IP_Address local{127, 0, 0, 1};
if (ans == local)
ans = localhostIP;
std::vector<u8> ansVector;
ansVector.resize(4);
*(IP_Address*)&ansVector[0] = ans;
DNS_ResponseEntry ansEntry(reqs[i], 1, 1, ansVector, 10800);
retPay->answers.push_back(ansEntry);
}
else
retPay->SetRCode(2); //ServerFailure
}
const u16 clientPort = state->clientPort;
delete state;
if (retPay->GetLength() > 512)
{
Console.Error("DEV9: Generated DNS response too large, dropping");
delete retPay;
outstandingQueries--;
return;
}
UDP_Packet* retUdp = new UDP_Packet(retPay);
retUdp->sourcePort = 53;
retUdp->destinationPort = clientPort;
dnsQueue.Enqueue(retUdp);
callback();
}
DNS_Server::~DNS_Server()
{
//Block untill DNS finished &
//Delete entries in queue
while (outstandingQueries != 0)
{
UDP_Packet* retPay = nullptr;
if (!dnsQueue.Dequeue(&retPay))
{
using namespace std::chrono_literals;
std::this_thread::sleep_for(10ms);
continue;
}
delete retPay;
outstandingQueries--;
}
#ifdef _WIN32
if (wsa_init)
WSACleanup();
#endif
}
#ifdef _WIN32
void DNS_Server::GetHost(std::string url, DNS_State* state)
{
//Need to convert to UTF16
const int size = MultiByteToWideChar(CP_UTF8, 0, url.c_str(), -1, nullptr, 0);
std::vector<wchar_t> converted_string(size);
MultiByteToWideChar(CP_UTF8, 0, url.c_str(), -1, converted_string.data(), converted_string.size());
ADDRINFOEX hints{0};
hints.ai_family = AF_INET;
GetAddrInfoExCallbackData* data = new GetAddrInfoExCallbackData();
data->state = state;
data->session = this;
data->url = url;
int ret = GetAddrInfoEx(converted_string.data(), nullptr, NS_ALL, 0, &hints, (ADDRINFOEX**)&data->result, nullptr, &data->overlapped, &DNS_Server::GetAddrInfoExCallback, &data->cancelHandle);
if (ret == WSA_IO_PENDING)
return;
else
GetAddrInfoExCallback(ret, -1, &data->overlapped);
}
void __stdcall DNS_Server::GetAddrInfoExCallback(DWORD dwError, DWORD dwBytes, OVERLAPPED* lpOverlapped)
{
GetAddrInfoExCallbackData* data = reinterpret_cast<GetAddrInfoExCallbackData*>(lpOverlapped);
int remaining = -1;
switch (dwError)
{
case NO_ERROR:
{
ADDRINFOEX* addrInfo = (ADDRINFOEX*)data->result;
while (addrInfo != nullptr && addrInfo->ai_family != AF_INET)
addrInfo = addrInfo->ai_next;
if (addrInfo == nullptr)
{
Console.Error("DEV9: Internal DNS failed to find host %s", data->url.c_str());
Console.Error("DEV9: with unexpected error code %d", -1);
remaining = data->state->AddNoAnswer(data->url);
break;
}
sockaddr_in* sockaddr = (sockaddr_in*)addrInfo->ai_addr;
remaining = data->state->AddAnswer(data->url, *(IP_Address*)&sockaddr->sin_addr);
break;
}
case WSAHOST_NOT_FOUND:
case WSATRY_AGAIN: //Nonauthoritative host not found
Console.Error("DEV9: Internal DNS failed to find host %s", data->url.c_str());
remaining = data->state->AddNoAnswer(data->url);
break;
default:
Console.Error("DEV9: Internal DNS failed to find host %s", data->url.c_str());
Console.Error("DEV9: with unexpected error code %d", dwError);
remaining = data->state->AddNoAnswer(data->url);
break;
}
pxAssert(remaining != -1);
if (remaining == 0)
data->session->FinaliseDNS(data->state);
//cleanup
if (data->result != nullptr)
FreeAddrInfoEx((ADDRINFOEX*)data->result);
delete data;
}
#elif defined(__POSIX__)
void DNS_Server::GetHost(std::string url, DNS_State* state)
{
//Need to spin up thread, pass the parms to it
std::thread GetHostThread(&DNS_Server::GetAddrInfoThread, this, url, state);
//detatch thread so that it can clean up itself
//we use another method of waiting for thread compleation
GetHostThread.detach();
}
void DNS_Server::GetAddrInfoThread(std::string url, DNS_State* state)
{
addrinfo hints{0};
hints.ai_family = AF_INET;
addrinfo* result = nullptr;
int error = getaddrinfo(url.c_str(), nullptr, &hints, &result);
int remaining = -1;
switch (error)
{
case 0:
{
addrinfo* retInfo = result;
while (retInfo != nullptr && retInfo->ai_family != AF_INET)
retInfo = retInfo->ai_next;
if (retInfo == nullptr)
{
Console.Error("DEV9: Internal DNS failed to find host %s", url.c_str());
Console.Error("DEV9: with unexpected error code %d", -1);
remaining = state->AddNoAnswer(url);
break;
}
sockaddr_in* sockaddr = (sockaddr_in*)retInfo->ai_addr;
remaining = state->AddAnswer(url, *(IP_Address*)&sockaddr->sin_addr);
break;
}
case EAI_NONAME:
case EAI_AGAIN: //Nonauthoritative host not found
Console.Error("DEV9: Internal DNS failed to find host %s", url.c_str());
remaining = state->AddNoAnswer(url);
break;
default:
Console.Error("DEV9: Internal DNS failed to find host %s", url.c_str());
Console.Error("DEV9: with unexpected error code %d", error);
remaining = state->AddNoAnswer(url);
break;
}
pxAssert(remaining != -1);
if (remaining == 0)
FinaliseDNS(state);
//cleanup
if (result != nullptr)
freeaddrinfo(result);
}
#endif
} // namespace InternalServers

View File

@ -0,0 +1,117 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <atomic>
#include <unordered_map>
#include <functional>
#ifdef _WIN32
#include <minwinbase.h>
#endif
#include "DEV9/SimpleQueue.h"
#include "DEV9/PacketReader/IP/IP_Packet.h"
#include "DEV9/PacketReader/IP/UDP/UDP_Packet.h"
#include "DEV9/PacketReader/IP/UDP/DNS/DNS_Packet.h"
#ifdef _WIN32
#include <winsock2.h>
#include <iphlpapi.h>
#elif defined(__POSIX__)
#include <sys/types.h>
#include <ifaddrs.h>
#endif
namespace InternalServers
{
class DNS_Server
{
private:
class DNS_State
{
public:
std::atomic<int> counter;
std::vector<std::string> questions;
PacketReader::IP::UDP::DNS::DNS_Packet* dns;
u16 clientPort;
private:
std::unordered_map<std::string, PacketReader::IP::IP_Address> answers;
public:
DNS_State(int count, std::vector<std::string> dnsQuestions, PacketReader::IP::UDP::DNS::DNS_Packet* dnsPacket, u16 port);
int AddAnswer(const std::string& answer, PacketReader::IP::IP_Address address);
int AddNoAnswer(const std::string& answer);
std::unordered_map<std::string, PacketReader::IP::IP_Address> GetAnswers();
};
#ifdef _WIN32
bool wsa_init = false;
#endif
std::function<void()> callback;
PacketReader::IP::IP_Address localhostIP{127, 0, 0, 1};
std::unordered_map<std::string, PacketReader::IP::IP_Address> hosts;
std::atomic<int> outstandingQueries{0};
SimpleQueue<PacketReader::IP::UDP::UDP_Packet*> dnsQueue;
public:
DNS_Server(std::function<void()> receivedcallback);
#ifdef _WIN32
void Init(PIP_ADAPTER_ADDRESSES adapter);
#elif defined(__POSIX__)
void Init(ifaddrs* adapter);
#endif
//Recv
PacketReader::IP::UDP::UDP_Packet* Recv();
//Expects a UDP_payload
bool Send(PacketReader::IP::UDP::UDP_Packet* payload);
//This might block for a large amount of time
//if destruction takes place during DNS request
//and the OS configured DNS server is unreachable
~DNS_Server();
private:
void LoadHostList();
bool CheckHostList(std::string url, DNS_State* state);
void GetHost(std::string url, DNS_State* state);
void FinaliseDNS(DNS_State* state);
#ifdef _WIN32
struct GetAddrInfoExCallbackData
{
OVERLAPPED overlapped{0};
void* result = nullptr;
HANDLE cancelHandle = nullptr;
DNS_State* state;
DNS_Server* session;
std::string url;
};
static void __stdcall GetAddrInfoExCallback(DWORD dwError, DWORD dwBytes, OVERLAPPED* lpOverlapped);
#elif defined(__POSIX__)
void GetAddrInfoThread(std::string url, DNS_State* state);
#endif
};
} // namespace InternalServers

View File

@ -20,6 +20,7 @@
#include "DEV9/DEV9.h"
#include "gui/AppConfig.h"
#include "DEV9/Config.h"
#include <unistd.h>
#include <sys/types.h>
@ -31,7 +32,6 @@
void SaveConf()
{
xmlDocPtr doc = NULL; /* document pointer */
xmlNodePtr root_node = NULL;
char buff[256];
@ -124,11 +124,12 @@ void SaveConf()
*have been allocated by the parser.
*/
xmlCleanupParser();
SaveDnsHosts();
}
void LoadConf()
{
const std::string file(GetSettingsFolder().Combine(wxString("DEV9.cfg")).GetFullPath());
if (-1 == access(file.c_str(), F_OK))
return;
@ -222,4 +223,6 @@ void LoadConf()
// free(configFile);
xmlFreeDoc(doc);
xmlCleanupParser();
LoadDnsHosts();
}

View File

@ -21,6 +21,7 @@
#include "DEV9/DEV9.h"
#include "gui/AppConfig.h"
#include "DEV9/Config.h"
#include "ws2tcpip.h"
@ -81,13 +82,18 @@ void SaveConf()
WritePrivateProfileInt(L"DEV9", L"ethEnable", config.ethEnable, file.c_str());
WritePrivateProfileInt(L"DEV9", L"hddEnable", config.hddEnable, file.c_str());
SaveDnsHosts();
}
void LoadConf()
{
const std::wstring file(GetSettingsFolder().Combine(wxString("DEV9.cfg")).GetFullPath());
if (FileExists(file.c_str()) == false)
{
LoadDnsHosts();
return;
}
wchar_t addrBuff[INET_ADDRSTRLEN] = {0};
wchar_t wEth[sizeof(config.Eth)] = {0};
@ -123,4 +129,6 @@ void LoadConf()
config.ethEnable = GetPrivateProfileInt(L"DEV9", L"ethEnable", config.ethEnable, file.c_str());
config.hddEnable = GetPrivateProfileInt(L"DEV9", L"hddEnable", config.hddEnable, file.c_str());
LoadDnsHosts();
}

View File

@ -21,6 +21,7 @@
#if defined(__POSIX__)
#include <pthread.h>
#endif
#include "net.h"
#include "DEV9.h"
#ifdef _WIN32
@ -279,6 +280,8 @@ void NetAdapter::InitInternalServer(ifaddrs* adapter)
if (config.InterceptDHCP)
dhcpServer.Init(adapter);
dnsServer.Init(adapter);
if (blocks())
{
internalRxThreadRunning.store(true);
@ -297,6 +300,8 @@ void NetAdapter::ReloadInternalServer(ifaddrs* adapter)
if (config.InterceptDHCP)
dhcpServer.Init(adapter);
dnsServer.Init(adapter);
}
bool NetAdapter::InternalServerRecv(NetPacket* pkt)
@ -314,6 +319,22 @@ bool NetAdapter::InternalServerRecv(NetPacket* pkt)
frame.WritePacket(pkt);
return true;
}
IP_Payload* ippay;
ippay = dnsServer.Recv();
if (ippay != nullptr)
{
IP_Packet* ippkt = new IP_Packet(ippay);
ippkt->destinationIP = ps2IP;
ippkt->sourceIP = internalIP;
EthernetFrame frame(ippkt);
memcpy(frame.sourceMAC, internalMAC, 6);
memcpy(frame.destinationMAC, ps2MAC, 6);
frame.protocol = (u16)EtherType::IPv4;
frame.WritePacket(pkt);
return true;
}
return false;
}
@ -340,6 +361,19 @@ bool NetAdapter::InternalServerSend(NetPacket* pkt)
if (ippkt.destinationIP == internalIP)
{
if (ippkt.protocol == (u16)IP_Type::UDP)
{
ps2IP = ippkt.sourceIP;
IP_PayloadPtr* ipPayload = static_cast<IP_PayloadPtr*>(ippkt.GetPayload());
UDP_Packet udppkt(ipPayload->data, ipPayload->GetLength());
if (udppkt.destinationPort == 53)
{
//Send DNS
return dnsServer.Send(&udppkt);
}
}
return true;
}
}

View File

@ -33,6 +33,7 @@
#include "PacketReader/IP/IP_Address.h"
#include "InternalServers/DHCP_Server.h"
#include "InternalServers/DNS_Server.h"
struct ConfigDEV9;
@ -87,6 +88,8 @@ protected:
static const u8 internalMAC[6];
private:
//Only set if packet sent to the internal IP address
PacketReader::IP::IP_Address ps2IP{0};
std::thread internalRxThread;
std::atomic<bool> internalRxThreadRunning{false};
@ -95,6 +98,7 @@ private:
bool internalRxHasData = false;
InternalServers::DHCP_Server dhcpServer = InternalServers::DHCP_Server([&] { InternalSignalReceived(); });
InternalServers::DNS_Server dnsServer = InternalServers::DNS_Server([&] { InternalSignalReceived(); });
public:
NetAdapter();

View File

@ -276,9 +276,11 @@
<ClCompile Include="DEV9\ATA\ATA_State.cpp" />
<ClCompile Include="DEV9\ATA\ATA_Transfer.cpp" />
<ClCompile Include="DEV9\ATA\HddCreate.cpp" />
<ClCompile Include="DEV9\DEV9Config.cpp" />
<ClCompile Include="DEV9\DEV9.cpp" />
<ClCompile Include="DEV9\flash.cpp" />
<ClCompile Include="DEV9\InternalServers\DHCP_Server.cpp" />
<ClCompile Include="DEV9\InternalServers\DNS_Server.cpp" />
<ClCompile Include="DEV9\PacketReader\EthernetFrame.cpp" />
<ClCompile Include="DEV9\PacketReader\IP\UDP\DHCP\DHCP_Options.cpp" />
<ClCompile Include="DEV9\PacketReader\IP\UDP\DHCP\DHCP_Packet.cpp" />
@ -724,6 +726,7 @@
<ClInclude Include="DEV9\Config.h" />
<ClInclude Include="DEV9\DEV9.h" />
<ClInclude Include="DEV9\InternalServers\DHCP_Server.h" />
<ClInclude Include="DEV9\InternalServers\DNS_Server.h" />
<ClInclude Include="DEV9\net.h" />
<ClInclude Include="DEV9\PacketReader\EthernetFrame.h" />
<ClInclude Include="DEV9\PacketReader\IP\UDP\DHCP\DHCP_Options.h" />

View File

@ -1175,6 +1175,9 @@
<ClCompile Include="DEV9\ATA\HddCreate.cpp">
<Filter>System\Ps2\DEV9\ATA</Filter>
</ClCompile>
<ClCompile Include="DEV9\DEV9Config.cpp">
<Filter>System\Ps2\DEV9</Filter>
</ClCompile>
<ClCompile Include="DEV9\DEV9.cpp">
<Filter>System\Ps2\DEV9</Filter>
</ClCompile>
@ -1184,6 +1187,9 @@
<ClCompile Include="DEV9\InternalServers\DHCP_Server.cpp">
<Filter>System\Ps2\DEV9\InternalServers</Filter>
</ClCompile>
<ClCompile Include="DEV9\InternalServers\DNS_Server.cpp">
<Filter>System\Ps2\DEV9\InternalServers</Filter>
</ClCompile>
<ClCompile Include="DEV9\PacketReader\IP\UDP\DHCP\DHCP_Options.cpp">
<Filter>System\Ps2\DEV9\PacketReader\IP\UDP\DHCP</Filter>
</ClCompile>
@ -2233,6 +2239,9 @@
<ClInclude Include="DEV9\InternalServers\DHCP_Server.h">
<Filter>System\Ps2\DEV9\InternalServers</Filter>
</ClInclude>
<ClInclude Include="DEV9\InternalServers\DNS_Server.h">
<Filter>System\Ps2\DEV9\InternalServers</Filter>
</ClInclude>
<ClInclude Include="DEV9\net.h">
<Filter>System\Ps2\DEV9</Filter>
</ClInclude>