DEV9: Have internal DHCP use AdapterUtils

This commit is contained in:
TheLastRar 2022-05-25 18:50:28 +01:00 committed by lightningterror
parent 35b5138593
commit 02f27f8cbc
2 changed files with 15 additions and 256 deletions

View File

@ -37,6 +37,7 @@
#include "DEV9/PacketReader/IP/UDP/DHCP/DHCP_Packet.h" #include "DEV9/PacketReader/IP/UDP/DHCP/DHCP_Packet.h"
#include "DEV9/DEV9.h" #include "DEV9/DEV9.h"
#include "DEV9/AdapterUtils.h"
using namespace PacketReader; using namespace PacketReader;
using namespace PacketReader::IP; using namespace PacketReader::IP;
@ -110,195 +111,6 @@ namespace InternalServers
AutoBroadcast(ps2IP, netmask); AutoBroadcast(ps2IP, netmask);
} }
#ifdef __POSIX__
//skipsEmpty
std::vector<std::string> DHCP_Server::SplitString(std::string str, char delimiter)
{
std::vector<std::string> ret;
size_t last = 0;
size_t next = 0;
std::string token;
while ((next = str.find(delimiter, last)) != std::string::npos)
{
token = str.substr(last, next - last);
if (next != last)
ret.push_back(token);
last = next + 1;
}
token = str.substr(last);
if (next != last)
ret.push_back(token);
return ret;
}
#ifdef __linux__
std::vector<IP_Address> DHCP_Server::GetGatewaysLinux(char* interfaceName)
{
///proc/net/route contains some information about gateway addresses,
//and separates the information about by each interface.
std::vector<IP_Address> collection;
std::vector<std::string> routeLines;
std::fstream route("/proc/net/route", std::ios::in);
if (route.fail())
{
route.close();
Console.Error("DHCP: Failed to open /proc/net/route");
return collection;
}
std::string line;
while (std::getline(route, line))
routeLines.push_back(line);
route.close();
//Columns are as follows (first-line header):
//Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
for (size_t i = 1; i < routeLines.size(); i++)
{
std::string line = routeLines[i];
if (line.rfind(interfaceName, 0) == 0)
{
std::vector<std::string> split = SplitString(line, '\t');
std::string gatewayIPHex = split[2];
int addressValue = std::stoi(gatewayIPHex, 0, 16);
//Skip device routes without valid NextHop IP address
if (addressValue != 0)
{
IP_Address gwIP = *(IP_Address*)&addressValue;
collection.push_back(gwIP);
}
}
}
return collection;
}
#elif defined(__FreeBSD__) || (__APPLE__)
std::vector<IP_Address> DHCP_Server::GetGatewaysBSD(char* interfaceName)
{
std::vector<IP_Address> collection;
//Get index for our adapter by matching the adapter name
int ifIndex = -1;
struct if_nameindex* ifNI;
ifNI = if_nameindex();
if (ifNI == nullptr)
{
Console.Error("DHCP: if_nameindex Failed");
return collection;
}
struct if_nameindex* i = ifNI;
while (i->if_index != 0 && i->if_name != nullptr)
{
if (strcmp(i->if_name, interfaceName) == 0)
{
ifIndex = i->if_index;
break;
}
i++;
}
if_freenameindex(ifNI);
//Check if we found the adapter
if (ifIndex == -1)
{
Console.Error("DHCP: Failed to get index for adapter");
return collection;
}
//Find the gateway by looking though the routing information
int name[] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_DUMP, 0};
size_t bufferLen = 0;
if (sysctl(name, 6, NULL, &bufferLen, NULL, 0) != 0)
{
Console.Error("DHCP: Failed to perform NET_RT_DUMP");
return collection;
}
//len is an estimate, double it to be safe
bufferLen *= 2;
std::unique_ptr<u8[]> buffer = std::make_unique<u8[]>(bufferLen);
if (sysctl(name, 6, buffer.get(), &bufferLen, NULL, 0) != 0)
{
Console.Error("DHCP: Failed to perform NET_RT_DUMP");
return collection;
}
rt_msghdr* hdr;
for (size_t i = 0; i < bufferLen; i += hdr->rtm_msglen)
{
hdr = (rt_msghdr*)&buffer[i];
if (hdr->rtm_flags & RTF_GATEWAY && hdr->rtm_addrs & RTA_GATEWAY && (hdr->rtm_index == ifIndex))
{
sockaddr* sockaddrs = (sockaddr*)(hdr + 1);
pxAssert(sockaddrs[RTAX_DST].sa_family == AF_INET);
//Default gateway has no destination address
sockaddr_in* sockaddr = (sockaddr_in*)&sockaddrs[RTAX_DST];
if (sockaddr->sin_addr.s_addr != 0)
continue;
sockaddr = (sockaddr_in*)&sockaddrs[RTAX_GATEWAY];
IP_Address gwIP = *(IP_Address*)&sockaddr->sin_addr;
collection.push_back(gwIP);
}
}
return collection;
}
#endif
std::vector<IP_Address> DHCP_Server::GetDNSUnix()
{
//On Linux and OSX, DNS is system wide, not adapter specific, so we can ignore adapter
// Parse /etc/resolv.conf for all of the "nameserver" entries.
// These are the DNS servers the machine is configured to use.
// On OSX, this file is not directly used by most processes for DNS
// queries/routing, but it is automatically generated instead, with
// the machine's DNS servers listed in it.
std::vector<IP_Address> collection;
std::fstream servers("/etc/resolv.conf", std::ios::in);
if (servers.fail())
{
servers.close();
Console.Error("DHCP: Failed to open /etc/resolv.conf");
return collection;
}
std::string line;
std::vector<std::string> serversLines;
while (std::getline(servers, line))
serversLines.push_back(line);
servers.close();
const IP_Address systemdDNS{127, 0, 0, 53};
for (size_t i = 1; i < serversLines.size(); i++)
{
std::string line = serversLines[i];
if (line.rfind("nameserver", 0) == 0)
{
std::vector<std::string> split = SplitString(line, '\t');
if (split.size() == 1)
split = SplitString(line, ' ');
std::string dns = split[1];
IP_Address address;
if (inet_pton(AF_INET, dns.c_str(), &address) != 1)
continue;
if (address == systemdDNS)
Console.Error("DHCP: systemd-resolved DNS server is not supported");
collection.push_back(address);
}
}
return collection;
}
#endif
#ifdef _WIN32 #ifdef _WIN32
void DHCP_Server::AutoNetmask(PIP_ADAPTER_ADDRESSES adapter) void DHCP_Server::AutoNetmask(PIP_ADAPTER_ADDRESSES adapter)
{ {
@ -316,23 +128,6 @@ namespace InternalServers
} }
} }
} }
void DHCP_Server::AutoGateway(PIP_ADAPTER_ADDRESSES adapter)
{
if (adapter != nullptr)
{
PIP_ADAPTER_GATEWAY_ADDRESS address = adapter->FirstGatewayAddress;
while (address != nullptr && address->Address.lpSockaddr->sa_family != AF_INET)
address = address->Next;
if (address != nullptr)
{
sockaddr_in* sockaddr = (sockaddr_in*)address->Address.lpSockaddr;
gateway = *(IP_Address*)&sockaddr->sin_addr;
}
}
}
#elif defined(__POSIX__) #elif defined(__POSIX__)
void DHCP_Server::AutoNetmask(ifaddrs* adapter) void DHCP_Server::AutoNetmask(ifaddrs* adapter)
{ {
@ -345,53 +140,28 @@ namespace InternalServers
} }
} }
} }
void DHCP_Server::AutoGateway(ifaddrs* adapter)
{
if (adapter != nullptr)
{
#ifdef __linux__
std::vector<IP_Address> gateways = GetGatewaysLinux(adapter->ifa_name);
if (gateways.size() > 0)
gateway = gateways[0];
#elif defined(__FreeBSD__) || (__APPLE__)
std::vector<IP_Address> gateways = GetGatewaysBSD(adapter->ifa_name);
if (gateways.size() > 0)
gateway = gateways[0];
#else
Console.Error("DHCP: Unsupported OS, can't find Gateway");
#endif
}
}
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
void DHCP_Server::AutoDNS(PIP_ADAPTER_ADDRESSES adapter, bool autoDNS1, bool autoDNS2) void DHCP_Server::AutoGateway(PIP_ADAPTER_ADDRESSES adapter)
#elif defined(__POSIX__)
void DHCP_Server::AutoGateway(ifaddrs* adapter)
#endif
{ {
std::vector<IP_Address> dnsIPs; std::vector<IP_Address> gateways = AdapterUtils::GetGateways(adapter);
if (adapter != nullptr) if (gateways.size() > 0)
{ gateway = gateways[0];
PIP_ADAPTER_DNS_SERVER_ADDRESS address = adapter->FirstDnsServerAddress; }
while (address != nullptr)
{ #ifdef _WIN32
if (address->Address.lpSockaddr->sa_family == AF_INET) void DHCP_Server::AutoDNS(PIP_ADAPTER_ADDRESSES adapter, bool autoDNS1, bool autoDNS2)
{
sockaddr_in* sockaddr = (sockaddr_in*)address->Address.lpSockaddr;
dnsIPs.push_back(*(IP_Address*)&sockaddr->sin_addr);
}
address = address->Next;
}
}
#elif defined(__POSIX__) #elif defined(__POSIX__)
void DHCP_Server::AutoDNS(ifaddrs* adapter, bool autoDNS1, bool autoDNS2) void DHCP_Server::AutoDNS(ifaddrs* adapter, bool autoDNS1, bool autoDNS2)
{
std::vector<IP_Address> dnsIPs = GetDNSUnix();
#endif #endif
{
std::vector<IP_Address> dnsIPs = AdapterUtils::GetDNS(adapter);
if (autoDNS1) if (autoDNS1)
{ {
//Auto DNS1 //Auto DNS1

View File

@ -61,20 +61,9 @@ namespace InternalServers
PacketReader::IP::UDP::UDP_Packet* Recv(); PacketReader::IP::UDP::UDP_Packet* Recv();
bool Send(PacketReader::IP::UDP::UDP_Packet* payload); bool Send(PacketReader::IP::UDP::UDP_Packet* payload);
#ifdef __linux__
static std::vector<PacketReader::IP::IP_Address> GetGatewaysLinux(char* interfaceName);
#elif defined(__FreeBSD__) || (__APPLE__)
static std::vector<PacketReader::IP::IP_Address> GetGatewaysBSD(char* interfaceName);
#endif
~DHCP_Server(); ~DHCP_Server();
private: private:
#ifdef __POSIX__
static std::vector<std::string> SplitString(std::string str, char delimiter);
static std::vector<PacketReader::IP::IP_Address> GetDNSUnix();
#endif
#ifdef _WIN32 #ifdef _WIN32
void AutoNetmask(PIP_ADAPTER_ADDRESSES adapter); void AutoNetmask(PIP_ADAPTER_ADDRESSES adapter);
void AutoGateway(PIP_ADAPTER_ADDRESSES adapter); void AutoGateway(PIP_ADAPTER_ADDRESSES adapter);