diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt
index 44fbed8ab4..3c468cc982 100644
--- a/pcsx2/CMakeLists.txt
+++ b/pcsx2/CMakeLists.txt
@@ -327,6 +327,7 @@ set(pcsx2DEV9Sources
DEV9/ATA/ATA_State.cpp
DEV9/ATA/ATA_Transfer.cpp
DEV9/ATA/HddCreate.cpp
+ DEV9/InternalServers/DHCP_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
@@ -351,6 +352,7 @@ set(pcsx2DEV9Headers
DEV9/ATA/ATA.h
DEV9/ATA/HddCreate.h
DEV9/DEV9.h
+ DEV9/InternalServers/DHCP_Server.cpp
DEV9/net.h
DEV9/PacketReader/IP/UDP/DHCP/DHCP_Options.h
DEV9/PacketReader/IP/UDP/DHCP/DHCP_Packet.h
diff --git a/pcsx2/DEV9/DEV9.h b/pcsx2/DEV9/DEV9.h
index eceba30695..0d898fabc9 100644
--- a/pcsx2/DEV9/DEV9.h
+++ b/pcsx2/DEV9/DEV9.h
@@ -28,6 +28,7 @@
#include "PS2Edefs.h"
#include "PS2Eext.h"
#include "net.h"
+#include "PacketReader/IP/IP_Address.h"
#include "ATA/ATA.h"
#ifdef _WIN32
@@ -60,6 +61,16 @@ struct Config
{
char Eth[256];
NetApi EthApi;
+ bool InterceptDHCP;
+ PacketReader::IP::IP_Address PS2IP;
+ PacketReader::IP::IP_Address Mask;
+ PacketReader::IP::IP_Address Gateway;
+ PacketReader::IP::IP_Address DNS1;
+ PacketReader::IP::IP_Address DNS2;
+ int AutoMask;
+ int AutoGateway;
+ int AutoDNS1;
+ int AutoDNS2;
#ifdef _WIN32
wchar_t Hdd[256];
#else
diff --git a/pcsx2/DEV9/InternalServers/DHCP_Server.cpp b/pcsx2/DEV9/InternalServers/DHCP_Server.cpp
new file mode 100644
index 0000000000..454de40d83
--- /dev/null
+++ b/pcsx2/DEV9/InternalServers/DHCP_Server.cpp
@@ -0,0 +1,497 @@
+/* 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 .
+ */
+
+#include "PrecompiledHeader.h"
+
+#include
+#ifdef __POSIX__
+#include
+#include
+#include
+#include
+#endif
+
+#include "DHCP_Server.h"
+#include "../PacketReader/IP/UDP/UDP_Packet.h"
+#include "../PacketReader/IP/UDP/DHCP/DHCP_Packet.h"
+
+#include "../DEV9.h"
+
+using namespace PacketReader;
+using namespace PacketReader::IP;
+using namespace PacketReader::IP::UDP;
+using namespace PacketReader::IP::UDP::DHCP;
+
+namespace InternalServers
+{
+ DHCP_Server::DHCP_Server(std::function receivedcallback)
+ : callback{receivedcallback}
+ {
+ }
+
+#ifdef _WIN32
+ void DHCP_Server::Init(PIP_ADAPTER_ADDRESSES adapter)
+#elif defined(__POSIX__)
+ void DHCP_Server::Init(ifaddrs* adapter)
+#endif
+ {
+ ps2IP = config.PS2IP;
+ netmask = {0};
+ gateway = {0};
+ dns1 = {0};
+ dns2 = {0};
+ broadcastIP = {0};
+
+ if (config.AutoMask)
+ AutoNetmask(adapter);
+ else
+ netmask = config.Mask;
+
+ if (config.AutoGateway)
+ AutoGateway(adapter);
+ else
+ gateway = config.Gateway;
+
+ if (!config.AutoDNS1)
+ dns1 = config.DNS1;
+
+ if (!config.AutoDNS2)
+ dns2 = config.DNS2;
+
+ AutoDNS(adapter, config.AutoDNS1, config.AutoDNS2);
+ AutoBroadcast(ps2IP, netmask);
+ }
+
+#ifdef __POSIX__
+ //skipsEmpty
+ std::vector DHCP_Server::SplitString(std::string str, char delimiter)
+ {
+ std::vector 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 DHCP_Server::GetGatewaysLinux(char* interfaceName)
+ {
+ ///proc/net/route contains some information about gateway addresses,
+ //and separates the information about by each interface.
+ std::vector collection;
+ std::vector 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 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;
+ }
+#endif
+ std::vector 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 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 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 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
+ void DHCP_Server::AutoNetmask(PIP_ADAPTER_ADDRESSES adapter)
+ {
+ if (adapter != nullptr)
+ {
+ PIP_ADAPTER_UNICAST_ADDRESS address = adapter->FirstUnicastAddress;
+ while (address != nullptr && address->Address.lpSockaddr->sa_family != AF_INET)
+ address = address->Next;
+
+ if (address != nullptr)
+ {
+ ULONG mask;
+ if (ConvertLengthToIpv4Mask(address->OnLinkPrefixLength, &mask) == NO_ERROR)
+ netmask.integer = mask;
+ }
+ }
+ }
+
+ 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__)
+ void DHCP_Server::AutoNetmask(ifaddrs* adapter)
+ {
+ if (adapter != nullptr)
+ {
+ if (adapter->ifa_netmask != nullptr && adapter->ifa_netmask->sa_family == AF_INET)
+ {
+ sockaddr_in* sockaddr = (sockaddr_in*)adapter->ifa_netmask;
+ netmask = *(IP_Address*)&sockaddr->sin_addr;
+ }
+ }
+ }
+
+ void DHCP_Server::AutoGateway(ifaddrs* adapter)
+ {
+ if (adapter != nullptr)
+ {
+#ifdef __linux__
+ std::vector gateways = GetGatewaysLinux(adapter->ifa_name);
+
+ if (gateways.size() > 0)
+ gateway = gateways[0];
+#else
+ Console.Error("DHCP: Unsupported OS, can't find Gateway");
+#endif
+ }
+ }
+#endif
+
+#ifdef _WIN32
+ void DHCP_Server::AutoDNS(PIP_ADAPTER_ADDRESSES adapter, bool autoDNS1, bool autoDNS2)
+ {
+ std::vector dnsIPs;
+
+ if (adapter != nullptr)
+ {
+ PIP_ADAPTER_DNS_SERVER_ADDRESS address = adapter->FirstDnsServerAddress;
+ while (address != nullptr)
+ {
+ if (address->Address.lpSockaddr->sa_family == AF_INET)
+ {
+ sockaddr_in* sockaddr = (sockaddr_in*)address->Address.lpSockaddr;
+ dnsIPs.push_back(*(IP_Address*)&sockaddr->sin_addr);
+ }
+ address = address->Next;
+ }
+ }
+#elif defined(__POSIX__)
+ void DHCP_Server::AutoDNS(ifaddrs* adapter, bool autoDNS1, bool autoDNS2)
+ {
+ std::vector dnsIPs = GetDNSUnix();
+#endif
+ if (autoDNS1)
+ {
+ //Auto DNS1
+ //If Adapter has DNS, add 1st entry
+ if (dnsIPs.size() >= 1)
+ dns1 = dnsIPs[0];
+
+ //Auto DNS1 & AutoDNS2
+ if (autoDNS2 && dnsIPs.size() >= 2)
+ dns2 = dnsIPs[1];
+ }
+ else if (autoDNS2)
+ {
+ //Manual DNS1 & Auto DNS2
+
+ //Use adapter's DNS2 if it has one
+ //otherwise use adapter's DNS1
+
+ if (dnsIPs.size() >= 1)
+ dns2 = dnsIPs[std::min((size_t)2, dnsIPs.size())];
+ }
+ if (dns1.integer == 0 && dns2.integer != 0)
+ {
+ Console.Error("DHCP: DNS1 is zero, but DNS2 is valid, using DNS2 as DNS1");
+ //no value for DNS1, but we have a value for DNS2
+ //set DNS1 to DNS2 and zero DNS2
+ dns1 = dns2;
+ dns2 = {0, 0, 0, 0};
+ }
+ }
+
+ void DHCP_Server::AutoBroadcast(IP_Address parPS2IP, IP_Address parNetmask)
+ {
+ if (parNetmask.integer != 0)
+ {
+ for (int i = 0; i < 4; i++)
+ broadcastIP.bytes[i] = ((parPS2IP.bytes[i]) | (~parNetmask.bytes[i]));
+ }
+ }
+
+ UDP_Packet* DHCP_Server::Recv()
+ {
+ UDP_Packet* payload;
+ if (recvBuff.Dequeue(&payload))
+ return payload;
+ return nullptr;
+ }
+
+ bool DHCP_Server::Send(UDP_Packet* payload)
+ {
+ UDP_Packet* udpPacket = static_cast(payload);
+ PayloadPtr* udpPayload = static_cast(udpPacket->GetPayload());
+ DHCP_Packet dhcp = DHCP_Packet(udpPayload->data, udpPayload->GetLength());
+
+ //State
+ u8 hType = dhcp.hardwareType;
+ u8 hLen = dhcp.hardwareAddressLength;
+ u32 xID = dhcp.transactionID;
+ u8* cMac = dhcp.clientHardwareAddress;
+ u32 cookie = dhcp.magicCookie;
+
+ u8 msg = 0;
+ std::vector reqList;
+
+ uint leaseTime = 86400;
+
+ for (size_t i = 0; i < dhcp.options.size(); i++)
+ {
+ switch (dhcp.options[i]->GetCode())
+ {
+ case 0:
+ continue;
+ case 1:
+ if (netmask != ((DHCPopSubnet*)dhcp.options[i])->subnetMask)
+ Console.Error("DHCP: SubnetMask missmatch");
+ break;
+ case 3:
+ if (((DHCPopRouter*)dhcp.options[i])->routers.size() != 1)
+ Console.Error("DHCP: Routers count missmatch");
+
+ if (gateway != ((DHCPopRouter*)dhcp.options[i])->routers[0])
+ Console.Error("DHCP: RouterIP missmatch");
+ break;
+ case 6:
+ if (((((DHCPopDNS*)dhcp.options[i])->dnsServers.size() == 0 && dns1.integer == 0) ||
+ (((DHCPopDNS*)dhcp.options[i])->dnsServers.size() == 1 && dns1.integer != 0 && dns2.integer == 0) ||
+ (((DHCPopDNS*)dhcp.options[i])->dnsServers.size() == 2 && dns2.integer != 0)) == false)
+ Console.Error("DHCP: DNS count missmatch");
+
+ if ((((DHCPopDNS*)dhcp.options[i])->dnsServers.size() > 0 && dns1 != ((DHCPopDNS*)dhcp.options[i])->dnsServers[0]) ||
+ (((DHCPopDNS*)dhcp.options[i])->dnsServers.size() > 1 && dns2 != ((DHCPopDNS*)dhcp.options[i])->dnsServers[1]))
+ Console.Error("DHCP: DNS missmatch");
+ break;
+ case 12:
+ //TODO use name?
+ break;
+ case 50:
+ if (ps2IP != ((DHCPopREQIP*)dhcp.options[i])->requestedIP)
+ Console.Error("DHCP: ReqIP missmatch");
+ break;
+ case 51:
+ leaseTime = ((DHCPopIPLT*)(dhcp.options[i]))->ipLeaseTime;
+ break;
+ case 53:
+ msg = ((DHCPopMSG*)(dhcp.options[i]))->message;
+ break;
+ case 54:
+ if (NetAdapter::internalIP != ((DHCPopSERVIP*)dhcp.options[i])->serverIP)
+ Console.Error("DHCP: ServIP missmatch");
+ break;
+ case 55:
+ reqList = ((DHCPopREQLIST*)(dhcp.options[i]))->requests;
+ break;
+ case 56: //String message
+ break;
+ case 57:
+ maxMs = ((DHCPopMMSGS*)(dhcp.options[i]))->maxMessageSize;
+ break;
+ case 60: //ClassID
+ case 61: //ClientID
+ case 255: //End
+ break;
+ default:
+ Console.Error("DHCP: Got Unhandled Option %d", dhcp.options[i]->GetCode());
+ break;
+ }
+ }
+
+ DHCP_Packet* retPay = new DHCP_Packet();
+ retPay->op = 2,
+ retPay->hardwareType = hType,
+ retPay->hardwareAddressLength = hLen,
+ retPay->transactionID = xID,
+
+ retPay->yourIP = ps2IP;
+ retPay->serverIP = NetAdapter::internalIP;
+
+ memcpy(retPay->clientHardwareAddress, cMac, 6);
+ retPay->magicCookie = cookie;
+
+ if (msg == 1 || msg == 3) //Fill out Requests
+ {
+ if (msg == 1)
+ retPay->options.push_back(new DHCPopMSG(2));
+ if (msg == 3)
+ retPay->options.push_back(new DHCPopMSG(5));
+
+ for (size_t i = 0; i < reqList.size(); i++)
+ {
+ switch (reqList[i])
+ {
+ case 1:
+ retPay->options.push_back(new DHCPopSubnet(netmask));
+ break;
+ case 3:
+ if (gateway.integer != 0)
+ {
+ std::vector routers;
+ routers.push_back(gateway);
+ retPay->options.push_back(new DHCPopRouter(routers));
+ }
+ break;
+ case 6:
+ if (dns1.integer != 0)
+ {
+ std::vector dns;
+ dns.push_back(dns1);
+ if (dns2.integer != 0)
+ dns.push_back(dns2);
+ retPay->options.push_back(new DHCPopDNS(dns));
+ }
+ break;
+ case 15:
+ retPay->options.push_back(new DHCPopDnsName("PCSX2"));
+ break;
+ case 28:
+ retPay->options.push_back(new DHCPopBCIP(broadcastIP));
+ break;
+ case 50:
+ retPay->options.push_back(new DHCPopREQIP(ps2IP));
+ break;
+ case 53: //Msg (Already added)
+ case 54: //Server Identifier (Already Added)
+ break;
+ default:
+ Console.Error("DHCP: Got Unhandled Request %d", reqList[i]);
+ break;
+ }
+ }
+ retPay->options.push_back(new DHCPopIPLT(leaseTime));
+ }
+ else if (msg == 7)
+ return true;
+
+ retPay->options.push_back(new DHCPopSERVIP(NetAdapter::internalIP));
+ retPay->options.push_back(new DHCPopEND());
+
+ retPay->maxLenth = maxMs;
+ UDP_Packet* retUdp = new UDP_Packet(retPay);
+ retUdp->sourcePort = 67;
+ retUdp->destinationPort = 68;
+
+ recvBuff.Enqueue(retUdp);
+ callback();
+ return true;
+ }
+
+ DHCP_Server::~DHCP_Server()
+ {
+ //Delete entries in queue
+ while (!recvBuff.IsQueueEmpty())
+ {
+ UDP_Packet* retPay = nullptr;
+ if (!recvBuff.Dequeue(&retPay))
+ {
+ std::this_thread::yield();
+ continue;
+ }
+
+ delete retPay;
+ }
+ }
+} // namespace InternalServers
diff --git a/pcsx2/DEV9/InternalServers/DHCP_Server.h b/pcsx2/DEV9/InternalServers/DHCP_Server.h
new file mode 100644
index 0000000000..afd16e47e4
--- /dev/null
+++ b/pcsx2/DEV9/InternalServers/DHCP_Server.h
@@ -0,0 +1,86 @@
+/* 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 .
+ */
+
+#pragma once
+
+#include
+
+#include "../SimpleQueue.h"
+#include "../PacketReader/IP/IP_Address.h"
+#include "../PacketReader/IP/UDP/UDP_Packet.h"
+
+#ifdef _WIN32
+#include
+#include
+#elif defined(__POSIX__)
+#include
+#include
+#endif
+
+namespace InternalServers
+{
+ class DHCP_Server
+ {
+ public:
+ PacketReader::IP::IP_Address ps2IP;
+ PacketReader::IP::IP_Address gateway;
+ PacketReader::IP::IP_Address broadcastIP;
+
+ private:
+ std::function callback;
+
+ PacketReader::IP::IP_Address dns1{0};
+ PacketReader::IP::IP_Address dns2{0};
+ PacketReader::IP::IP_Address netmask{0};
+
+ SimpleQueue recvBuff;
+
+ u16 maxMs = 576;
+
+ public:
+ DHCP_Server(std::function receivedcallback);
+
+#ifdef _WIN32
+ void Init(PIP_ADAPTER_ADDRESSES adapter);
+#elif defined(__POSIX__)
+ void Init(ifaddrs* adapter);
+#endif
+
+ PacketReader::IP::UDP::UDP_Packet* Recv();
+ bool Send(PacketReader::IP::UDP::UDP_Packet* payload);
+
+ ~DHCP_Server();
+
+ private:
+#ifdef __POSIX__
+ static std::vector SplitString(std::string str, char delimiter);
+#ifdef __linux__
+ static std::vector GetGatewaysLinux(char* interfaceName);
+#endif
+ static std::vector GetDNSUnix();
+#endif
+
+#ifdef _WIN32
+ void AutoNetmask(PIP_ADAPTER_ADDRESSES adapter);
+ void AutoGateway(PIP_ADAPTER_ADDRESSES adapter);
+ void AutoDNS(PIP_ADAPTER_ADDRESSES adapter, bool autoDNS1, bool autoDNS2);
+#elif defined(__POSIX__)
+ void AutoNetmask(ifaddrs* adapter);
+ void AutoGateway(ifaddrs* adapter);
+ void AutoDNS(ifaddrs* adapter, bool autoDNS1, bool autoDNS2);
+#endif
+ void AutoBroadcast(PacketReader::IP::IP_Address parPS2IP, PacketReader::IP::IP_Address parNetmask);
+ };
+} // namespace InternalServers
diff --git a/pcsx2/DEV9/Linux/Config.cpp b/pcsx2/DEV9/Linux/Config.cpp
index 1189b1c97b..589a33e2c2 100644
--- a/pcsx2/DEV9/Linux/Config.cpp
+++ b/pcsx2/DEV9/Linux/Config.cpp
@@ -16,8 +16,8 @@
#include "PrecompiledHeader.h"
#include
+#include
-//#include
#include "../DEV9.h"
#include "AppConfig.h"
@@ -50,6 +50,46 @@ void SaveConf()
xmlNewChild(root_node, NULL, BAD_CAST "EthApi",
BAD_CAST buff);
+ sprintf(buff, "%d", config.InterceptDHCP);
+ xmlNewChild(root_node, NULL, BAD_CAST "InterceptDHCP",
+ BAD_CAST buff);
+
+ inet_ntop(AF_INET, &config.PS2IP, buff, 256);
+ xmlNewChild(root_node, NULL, BAD_CAST "PS2IP",
+ BAD_CAST buff);
+
+ inet_ntop(AF_INET, &config.Mask, buff, 256);
+ xmlNewChild(root_node, NULL, BAD_CAST "Subnet",
+ BAD_CAST buff);
+
+ sprintf(buff, "%d", config.AutoMask);
+ xmlNewChild(root_node, NULL, BAD_CAST "AutoSubnet",
+ BAD_CAST buff);
+
+ inet_ntop(AF_INET, &config.Gateway, buff, 256);
+ xmlNewChild(root_node, NULL, BAD_CAST "Gateway",
+ BAD_CAST buff);
+
+ sprintf(buff, "%d", config.AutoGateway);
+ xmlNewChild(root_node, NULL, BAD_CAST "AutoGateway",
+ BAD_CAST buff);
+
+ inet_ntop(AF_INET, &config.DNS1, buff, 256);
+ xmlNewChild(root_node, NULL, BAD_CAST "DNS1",
+ BAD_CAST buff);
+
+ sprintf(buff, "%d", config.AutoDNS1);
+ xmlNewChild(root_node, NULL, BAD_CAST "AutoDNS1",
+ BAD_CAST buff);
+
+ inet_ntop(AF_INET, &config.DNS2, buff, 256);
+ xmlNewChild(root_node, NULL, BAD_CAST "DNS2",
+ BAD_CAST buff);
+
+ sprintf(buff, "%d", config.AutoDNS2);
+ xmlNewChild(root_node, NULL, BAD_CAST "AutoDNS2",
+ BAD_CAST buff);
+
xmlNewChild(root_node, NULL, BAD_CAST "Hdd",
BAD_CAST config.Hdd);
@@ -94,6 +134,7 @@ void LoadConf()
return;
memset(&config, 0, sizeof(config));
+ config.EthApi = NetApi::PCAP_Switched;
// Read the files
xmlDoc* doc = NULL;
@@ -106,7 +147,6 @@ void LoadConf()
SysMessage("Unable to parse configuration file! Suggest deleting it and starting over.");
}
- bool foundEthType = false;
for (cur_node = xmlDocGetRootElement(doc)->children; cur_node; cur_node = cur_node->next)
{
if (cur_node->type == XML_ELEMENT_NODE)
@@ -118,9 +158,48 @@ void LoadConf()
}
if (0 == strcmp((const char*)cur_node->name, "EthApi"))
{
- foundEthType = true;
config.EthApi = (NetApi)atoi((const char*)xmlNodeGetContent(cur_node));
}
+ if (0 == strcmp((const char*)cur_node->name, "InterceptDHCP"))
+ {
+ config.InterceptDHCP = atoi((const char*)xmlNodeGetContent(cur_node));
+ }
+ if (0 == strcmp((const char*)cur_node->name, "PS2IP"))
+ {
+ inet_pton(AF_INET, (const char*)xmlNodeGetContent(cur_node), &config.PS2IP);
+ }
+ if (0 == strcmp((const char*)cur_node->name, "Subnet"))
+ {
+ inet_pton(AF_INET, (const char*)xmlNodeGetContent(cur_node), &config.Mask);
+ }
+ if (0 == strcmp((const char*)cur_node->name, "AutoSubnet"))
+ {
+ config.AutoMask = atoi((const char*)xmlNodeGetContent(cur_node));
+ }
+ if (0 == strcmp((const char*)cur_node->name, "Gateway"))
+ {
+ inet_pton(AF_INET, (const char*)xmlNodeGetContent(cur_node), &config.Gateway);
+ }
+ if (0 == strcmp((const char*)cur_node->name, "AutoGateway"))
+ {
+ config.AutoGateway = atoi((const char*)xmlNodeGetContent(cur_node));
+ }
+ if (0 == strcmp((const char*)cur_node->name, "DNS1"))
+ {
+ inet_pton(AF_INET, (const char*)xmlNodeGetContent(cur_node), &config.DNS1);
+ }
+ if (0 == strcmp((const char*)cur_node->name, "AutoDNS1"))
+ {
+ config.AutoDNS1 = atoi((const char*)xmlNodeGetContent(cur_node));
+ }
+ if (0 == strcmp((const char*)cur_node->name, "DNS2"))
+ {
+ inet_pton(AF_INET, (const char*)xmlNodeGetContent(cur_node), &config.DNS2);
+ }
+ if (0 == strcmp((const char*)cur_node->name, "AutoDNS2"))
+ {
+ config.AutoDNS2 = atoi((const char*)xmlNodeGetContent(cur_node));
+ }
if (0 == strcmp((const char*)cur_node->name, "Hdd"))
{
strcpy(config.Hdd, (const char*)xmlNodeGetContent(cur_node));
@@ -140,9 +219,6 @@ void LoadConf()
}
}
- if (!foundEthType)
- config.EthApi = NetApi::PCAP_Switched;
-
// free(configFile);
xmlFreeDoc(doc);
xmlCleanupParser();
diff --git a/pcsx2/DEV9/Linux/Linux.cpp b/pcsx2/DEV9/Linux/Linux.cpp
index ad78de9118..2ce470e28e 100644
--- a/pcsx2/DEV9/Linux/Linux.cpp
+++ b/pcsx2/DEV9/Linux/Linux.cpp
@@ -16,6 +16,7 @@
#include "PrecompiledHeader.h"
#include
+#include
#include
@@ -34,13 +35,109 @@
#include "pcap.h"
#include "../pcap_io.h"
#include "../net.h"
+#include "../PacketReader/IP/IP_Address.h"
#include "AppCoreThread.h"
#include "../ATA/HddCreate.h"
+using PacketReader::IP::IP_Address;
+
static GtkBuilder* builder = nullptr;
std::vector adapters;
+void IPControl_SetValue(GtkEntry* entryCtl, IP_Address value)
+{
+ char addrBuff[INET_ADDRSTRLEN] = {0};
+ inet_ntop(AF_INET, &value, addrBuff, INET_ADDRSTRLEN);
+ gtk_entry_set_text(entryCtl, addrBuff);
+}
+IP_Address IPControl_GetValue(GtkEntry* entryCtl)
+{
+ IP_Address ret;
+ if (inet_pton(AF_INET, gtk_entry_get_text(entryCtl), &ret) == 1)
+ return ret;
+ Console.Error("Invalid IP address entered");
+ return {0};
+}
+
+void IPControl_Enable(GtkEntry *ipEntry, bool enabled, IP_Address value)
+{
+ if (enabled)
+ {
+ gtk_widget_set_sensitive((GtkWidget*)ipEntry, true);
+ IPControl_SetValue(ipEntry, value);
+ }
+ else
+ {
+ gtk_widget_set_sensitive((GtkWidget*)ipEntry, false);
+ IPControl_SetValue(ipEntry, {0});
+ }
+}
+
+void OnAutoMaskChanged(GtkToggleButton *togglebutton, gpointer usr_data)
+{
+ IPControl_Enable((GtkEntry*)gtk_builder_get_object(builder, "IDC_IPADDRESS_SUBNET"), !gtk_toggle_button_get_active(togglebutton), config.Mask);
+}
+
+void OnAutoGatewayChanged(GtkToggleButton *togglebutton, gpointer usr_data)
+{
+ IPControl_Enable((GtkEntry*)gtk_builder_get_object(builder, "IDC_IPADDRESS_GATEWAY"), !gtk_toggle_button_get_active(togglebutton), config.Gateway);
+}
+
+void OnAutoDNS1Changed(GtkToggleButton *togglebutton, gpointer usr_data)
+{
+ IPControl_Enable((GtkEntry*)gtk_builder_get_object(builder, "IDC_IPADDRESS_DNS1"), !gtk_toggle_button_get_active(togglebutton), config.DNS1);
+}
+
+void OnAutoDNS2Changed(GtkToggleButton *togglebutton, gpointer usr_data)
+{
+ IPControl_Enable((GtkEntry*)gtk_builder_get_object(builder, "IDC_IPADDRESS_DNS2"), !gtk_toggle_button_get_active(togglebutton), config.DNS2);
+}
+
+void OnInterceptChanged(GtkToggleButton *togglebutton, gpointer usr_data)
+{
+ if (gtk_toggle_button_get_active(togglebutton))
+ {
+ gtk_widget_set_sensitive((GtkWidget*)gtk_builder_get_object(builder, "IDC_IPADDRESS_IP"), true);
+ IPControl_SetValue((GtkEntry*)gtk_builder_get_object(builder, "IDC_IPADDRESS_IP"), config.PS2IP);
+
+ gtk_widget_set_sensitive((GtkWidget*)gtk_builder_get_object(builder, "IDC_CHECK_SUBNET"), true);
+ gtk_widget_set_sensitive((GtkWidget*)gtk_builder_get_object(builder, "IDC_CHECK_GATEWAY"), true);
+ gtk_widget_set_sensitive((GtkWidget*)gtk_builder_get_object(builder, "IDC_CHECK_DNS1"), true);
+ gtk_widget_set_sensitive((GtkWidget*)gtk_builder_get_object(builder, "IDC_CHECK_DNS2"), true);
+
+ gtk_toggle_button_set_active((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_SUBNET"), config.AutoMask);
+ gtk_toggle_button_set_active((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_GATEWAY"), config.AutoGateway);
+ gtk_toggle_button_set_active((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_DNS1"), config.AutoDNS1);
+ gtk_toggle_button_set_active((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_DNS2"), config.AutoDNS2);
+
+ OnAutoMaskChanged((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_SUBNET"), nullptr);
+ OnAutoGatewayChanged((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_GATEWAY"), nullptr);
+ OnAutoDNS1Changed((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_DNS1"), nullptr);
+ OnAutoDNS2Changed((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_DNS2"), nullptr);
+ }
+ else
+ {
+ gtk_widget_set_sensitive((GtkWidget*)gtk_builder_get_object(builder, "IDC_IPADDRESS_IP"), false);
+ IPControl_SetValue((GtkEntry*)gtk_builder_get_object(builder, "IDC_IPADDRESS_IP"), {0});
+
+ gtk_widget_set_sensitive((GtkWidget*)gtk_builder_get_object(builder, "IDC_CHECK_SUBNET"), false);
+ gtk_widget_set_sensitive((GtkWidget*)gtk_builder_get_object(builder, "IDC_CHECK_GATEWAY"), false);
+ gtk_widget_set_sensitive((GtkWidget*)gtk_builder_get_object(builder, "IDC_CHECK_DNS1"), false);
+ gtk_widget_set_sensitive((GtkWidget*)gtk_builder_get_object(builder, "IDC_CHECK_DNS2"), false);
+
+ gtk_toggle_button_set_active((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_SUBNET"), true);
+ gtk_toggle_button_set_active((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_GATEWAY"), true);
+ gtk_toggle_button_set_active((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_DNS1"), true);
+ gtk_toggle_button_set_active((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_DNS2"), true);
+
+ IPControl_Enable((GtkEntry*)gtk_builder_get_object(builder, "IDC_IPADDRESS_SUBNET"), false, config.Mask);
+ IPControl_Enable((GtkEntry*)gtk_builder_get_object(builder, "IDC_IPADDRESS_GATEWAY"), false, config.Gateway);
+ IPControl_Enable((GtkEntry*)gtk_builder_get_object(builder, "IDC_IPADDRESS_DNS1"), false, config.DNS1);
+ IPControl_Enable((GtkEntry*)gtk_builder_get_object(builder, "IDC_IPADDRESS_DNS2"), false, config.DNS2);
+ }
+}
+
void OnInitDialog()
{
gint idx = 0;
@@ -67,6 +164,9 @@ void OnInitDialog()
idx++;
}
+ gtk_toggle_button_set_active((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_DHCP"), config.InterceptDHCP);
+ OnInterceptChanged((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_DHCP"), nullptr);
+
gtk_entry_set_text((GtkEntry*)gtk_builder_get_object(builder, "IDC_HDDFILE"), config.Hdd);
//HDDSpin
@@ -147,6 +247,28 @@ void OnOk()
config.EthApi = adapters[ethIndex].type;
}
+ config.InterceptDHCP = gtk_toggle_button_get_active((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_DHCP"));
+ if (config.InterceptDHCP)
+ {
+ config.PS2IP = IPControl_GetValue((GtkEntry*)gtk_builder_get_object(builder, "IDC_IPADDRESS_IP"));
+
+ config.AutoMask = gtk_toggle_button_get_active((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_SUBNET"));
+ if (!config.AutoMask)
+ config.Mask = IPControl_GetValue((GtkEntry*)gtk_builder_get_object(builder, "IDC_IPADDRESS_SUBNET"));
+
+ config.AutoGateway = gtk_toggle_button_get_active((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_GATEWAY"));
+ if (!config.AutoGateway)
+ config.Gateway = IPControl_GetValue((GtkEntry*)gtk_builder_get_object(builder, "IDC_IPADDRESS_GATEWAY"));
+
+ config.AutoDNS1 = gtk_toggle_button_get_active((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_DNS1"));
+ if (!config.AutoDNS1)
+ config.DNS1 = IPControl_GetValue((GtkEntry*)gtk_builder_get_object(builder, "IDC_IPADDRESS_DNS1"));
+
+ config.AutoDNS2 = gtk_toggle_button_get_active((GtkToggleButton*)gtk_builder_get_object(builder, "IDC_CHECK_DNS2"));
+ if (!config.AutoDNS2)
+ config.DNS2 = IPControl_GetValue((GtkEntry*)gtk_builder_get_object(builder, "IDC_IPADDRESS_DNS2"));
+ }
+
strcpy(config.Hdd, gtk_entry_get_text((GtkEntry*)gtk_builder_get_object(builder, "IDC_HDDFILE")));
config.HddSize = gtk_spin_button_get_value((GtkSpinButton*)gtk_builder_get_object(builder, "IDC_HDDSIZE_SPIN")) * 1024;
@@ -184,6 +306,11 @@ void DEV9configure()
{
builder = gtk_builder_new();
gtk_builder_add_callback_symbols(builder,
+ "OnInterceptChanged", G_CALLBACK(&OnInterceptChanged),
+ "OnAutoMaskChanged", G_CALLBACK(&OnAutoMaskChanged),
+ "OnAutoGatewayChanged", G_CALLBACK(&OnAutoGatewayChanged),
+ "OnAutoDNS1Changed", G_CALLBACK(&OnAutoDNS1Changed),
+ "OnAutoDNS2Changed", G_CALLBACK(&OnAutoDNS2Changed),
"OnBrowse", G_CALLBACK(&OnBrowse),
"OnSpin", G_CALLBACK(&OnSpin),
"OnSlide", G_CALLBACK(&OnSlide), nullptr);
diff --git a/pcsx2/DEV9/Linux/dev9.ui b/pcsx2/DEV9/Linux/dev9.ui
index 9e75987da3..903c6668f2 100644
--- a/pcsx2/DEV9/Linux/dev9.ui
+++ b/pcsx2/DEV9/Linux/dev9.ui
@@ -120,12 +120,14 @@
1
0
+ 2
@@ -133,6 +135,212 @@
0
+
+
+
+ 0
+ 1
+
+
+
+
+
+ 1
+ 1
+ 2
+
+
+
+
+
+ 0
+ 2
+
+
+
+
+
+ 0
+ 3
+
+
+
+
+
+ 0
+ 4
+
+
+
+
+
+ 0
+ 5
+
+
+
+
+
+ 0
+ 6
+
+
+
+
+
+ 1
+ 2
+
+
+
+
+
+ 1
+ 3
+
+
+
+
+
+ 1
+ 4
+
+
+
+
+
+ 1
+ 5
+
+
+
+
+
+ 1
+ 6
+
+
+
+
+
+ 2
+ 3
+
+
+
+
+
+ 2
+ 4
+
+
+
+
+
+ 2
+ 5
+
+
+
+
+
+ 2
+ 6
+
+
+
+
+
0
diff --git a/pcsx2/DEV9/Win32/DEV9WinConfig.cpp b/pcsx2/DEV9/Win32/DEV9WinConfig.cpp
index c698383650..5a9e737974 100644
--- a/pcsx2/DEV9/Win32/DEV9WinConfig.cpp
+++ b/pcsx2/DEV9/Win32/DEV9WinConfig.cpp
@@ -19,10 +19,11 @@
#include
-//#include
#include "..\DEV9.h"
#include "AppConfig.h"
+#include "ws2tcpip.h"
+
BOOL WritePrivateProfileInt(LPCWSTR lpAppName, LPCWSTR lpKeyName, int intvar, LPCWSTR lpFileName)
{
return WritePrivateProfileString(lpAppName, lpKeyName, std::to_wstring(intvar).c_str(), lpFileName);
@@ -47,13 +48,37 @@ void SaveConf()
nfile.write((char*)L"[DEV9]", 14);
nfile.close();
+ wchar_t addrBuff[INET_ADDRSTRLEN] = {0};
wchar_t wEth[sizeof(config.Eth)] = {0};
mbstowcs(wEth, config.Eth, sizeof(config.Eth) - 1);
WritePrivateProfileString(L"DEV9", L"Eth", wEth, file.c_str());
- WritePrivateProfileInt(L"DEV9", L"EthApi", (int)config.EthApi, file.c_str());
- WritePrivateProfileString(L"DEV9", L"Hdd", config.Hdd, file.c_str());
+ WritePrivateProfileInt(L"DEV9", L"EthApi", (int)config.EthApi, file.c_str());
+ WritePrivateProfileInt(L"DEV9", L"InterceptDHCP", config.InterceptDHCP, file.c_str());
+
+ InetNtop(AF_INET, &config.PS2IP, addrBuff, INET_ADDRSTRLEN);
+ WritePrivateProfileString(L"DEV9", L"PS2IP", addrBuff, file.c_str());
+
+ InetNtop(AF_INET, &config.Mask, addrBuff, INET_ADDRSTRLEN);
+ WritePrivateProfileString(L"DEV9", L"Subnet", addrBuff, file.c_str());
+ WritePrivateProfileInt(L"DEV9", L"AutoSubnet", config.AutoMask, file.c_str());
+
+ InetNtop(AF_INET, &config.Gateway, addrBuff, INET_ADDRSTRLEN);
+ WritePrivateProfileString(L"DEV9", L"Gateway", addrBuff, file.c_str());
+ WritePrivateProfileInt(L"DEV9", L"AutoGateway", config.AutoGateway, file.c_str());
+
+ InetNtop(AF_INET, &config.DNS1, addrBuff, INET_ADDRSTRLEN);
+ WritePrivateProfileString(L"DEV9", L"DNS1", addrBuff, file.c_str());
+ WritePrivateProfileInt(L"DEV9", L"AutoDNS1", config.AutoDNS1, file.c_str());
+
+ InetNtop(AF_INET, &config.DNS2, addrBuff, INET_ADDRSTRLEN);
+ WritePrivateProfileString(L"DEV9", L"DNS2", addrBuff, file.c_str());
+ WritePrivateProfileInt(L"DEV9", L"AutoDNS2", config.AutoDNS2, file.c_str());
+
+
+ WritePrivateProfileString(L"DEV9", L"Hdd", config.Hdd, file.c_str());
WritePrivateProfileInt(L"DEV9", L"HddSize", config.HddSize, file.c_str());
+
WritePrivateProfileInt(L"DEV9", L"ethEnable", config.ethEnable, file.c_str());
WritePrivateProfileInt(L"DEV9", L"hddEnable", config.hddEnable, file.c_str());
}
@@ -64,15 +89,38 @@ void LoadConf()
if (FileExists(file.c_str()) == false)
return;
+ wchar_t addrBuff[INET_ADDRSTRLEN] = {0};
wchar_t wEth[sizeof(config.Eth)] = {0};
mbstowcs(wEth, ETH_DEF, sizeof(config.Eth) - 1);
GetPrivateProfileString(L"DEV9", L"Eth", wEth, wEth, sizeof(config.Eth), file.c_str());
wcstombs(config.Eth, wEth, sizeof(config.Eth) - 1);
+
config.EthApi = (NetApi)GetPrivateProfileInt(L"DEV9", L"EthApi", (int)NetApi::TAP, file.c_str());
+ config.InterceptDHCP = GetPrivateProfileInt(L"DEV9", L"InterceptDHCP", config.InterceptDHCP, file.c_str());
+
+ GetPrivateProfileString(L"DEV9", L"PS2IP", L"0.0.0.0", addrBuff, INET_ADDRSTRLEN, file.c_str());
+ InetPton(AF_INET, addrBuff, &config.PS2IP);
+
+ GetPrivateProfileString(L"DEV9", L"Subnet", L"0.0.0.0", addrBuff, INET_ADDRSTRLEN, file.c_str());
+ InetPton(AF_INET, addrBuff, &config.Mask);
+ config.AutoMask = GetPrivateProfileInt(L"DEV9", L"AutoSubnet", config.AutoMask, file.c_str());
+
+ GetPrivateProfileString(L"DEV9", L"Gateway", L"0.0.0.0", addrBuff, INET_ADDRSTRLEN, file.c_str());
+ InetPton(AF_INET, addrBuff, &config.Gateway);
+ config.AutoGateway = GetPrivateProfileInt(L"DEV9", L"AutoGateway", config.AutoGateway, file.c_str());
+
+ GetPrivateProfileString(L"DEV9", L"DNS1", L"0.0.0.0", addrBuff, INET_ADDRSTRLEN, file.c_str());
+ InetPton(AF_INET, addrBuff, &config.DNS1);
+ config.AutoDNS1 = GetPrivateProfileInt(L"DEV9", L"AutoDNS1", config.AutoDNS1, file.c_str());
+
+ GetPrivateProfileString(L"DEV9", L"DNS2", L"0.0.0.0", addrBuff, INET_ADDRSTRLEN, file.c_str());
+ InetPton(AF_INET, addrBuff, &config.DNS2);
+ config.AutoDNS2 = GetPrivateProfileInt(L"DEV9", L"AutoDNS2", config.AutoDNS2, file.c_str());
+
GetPrivateProfileString(L"DEV9", L"Hdd", HDD_DEF, config.Hdd, sizeof(config.Hdd), file.c_str());
-
config.HddSize = GetPrivateProfileInt(L"DEV9", L"HddSize", config.HddSize, file.c_str());
+
config.ethEnable = GetPrivateProfileInt(L"DEV9", L"ethEnable", config.ethEnable, file.c_str());
config.hddEnable = GetPrivateProfileInt(L"DEV9", L"hddEnable", config.hddEnable, file.c_str());
}
diff --git a/pcsx2/DEV9/Win32/DEV9ghzdrk.rc b/pcsx2/DEV9/Win32/DEV9ghzdrk.rc
index f13fc7f5f4..c7fd857779 100644
--- a/pcsx2/DEV9/Win32/DEV9ghzdrk.rc
+++ b/pcsx2/DEV9/Win32/DEV9ghzdrk.rc
@@ -54,30 +54,46 @@ END
// Dialog
//
-IDD_CONFIG DIALOGEX 0, 0, 290, 205
+IDD_CONFIG DIALOGEX 0, 0, 291, 320
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Network and HDD Settings"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
- DEFPUSHBUTTON "OK",IDOK,92,185,50,14
- PUSHBUTTON "Cancel",IDCANCEL,148,185,50,14
+ DEFPUSHBUTTON "OK",IDOK,92,300,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,148,300,50,14
LTEXT "DEV9 Type:",IDC_STATIC,15,10,41,11,SS_CENTERIMAGE
COMBOBOX IDC_BAYTYPE,61,8,223,47,CBS_DROPDOWNLIST | CBS_SORT | WS_DISABLED
- GROUPBOX "Ethernet",IDC_STATIC,7,30,277,50
+ GROUPBOX "Ethernet",IDC_STATIC,7,30,277,164
CONTROL "Enabled",IDC_ETHENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,45,42,8
LTEXT "Ethernet Device:",IDC_STATIC,26,60,60,8,SS_CENTERIMAGE
COMBOBOX IDC_ETHDEV,94,58,182,82,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
- GROUPBOX "Hard Disk Drive",IDC_STATIC,7,90,277,85
- CONTROL "Enabled",IDC_HDDENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,105,42,8
- LTEXT "HDD File:",IDC_STATIC,26,120,60,8,SS_CENTERIMAGE
- EDITTEXT IDC_HDDFILE,94,118,130,13,ES_AUTOHSCROLL
- CONTROL "",IDC_HDDSIZE_SLIDER,"msctls_trackbar32",WS_TABSTOP,90,141,150,15
- LTEXT "HDD Size (GiB):",IDC_STATIC,26,143,60,8,SS_CENTERIMAGE
- EDITTEXT IDC_HDDSIZE_TEXT,240,141,25,13,ES_AUTOHSCROLL | ES_NUMBER
- CONTROL "",IDC_HDDSIZE_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_AUTOBUDDY | UDS_ARROWKEYS,265,141,11,13
- LTEXT "8 GiB",IDC_STATIC,89,158,17,8
- LTEXT "120 GiB",IDC_STATIC,219,157,25,8,0,WS_EX_RIGHT
- PUSHBUTTON "Browse",IDC_BROWSE,226,117,50,15
+ GROUPBOX "Hard Disk Drive",IDC_STATIC,7,205,277,85
+ CONTROL "Enabled",IDC_HDDENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,220,42,8
+ LTEXT "HDD File:",IDC_STATIC,26,235,60,8,SS_CENTERIMAGE
+ EDITTEXT IDC_HDDFILE,94,233,130,13,ES_AUTOHSCROLL
+ CONTROL "",IDC_HDDSIZE_SLIDER,"msctls_trackbar32",WS_TABSTOP,90,256,150,15
+ LTEXT "HDD Size (GiB):",IDC_STATIC,26,258,60,8,SS_CENTERIMAGE
+ EDITTEXT IDC_HDDSIZE_TEXT,240,256,25,13,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_HDDSIZE_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_AUTOBUDDY | UDS_ARROWKEYS,265,256,11,13
+ LTEXT "8 GiB",IDC_STATIC,89,273,17,8
+ LTEXT "120 GiB",IDC_STATIC,219,272,25,8,0,WS_EX_RIGHT
+ PUSHBUTTON "Browse",IDC_BROWSE,226,232,50,15
+ CONTROL "",IDC_IPADDRESS_IP,"SysIPAddress32",WS_TABSTOP,95,92,100,15
+ LTEXT "Intercept DHCP:",IDC_STATIC,26,77,60,8,SS_CENTERIMAGE
+ LTEXT "PS2 Address:",IDC_STATIC,26,94,60,8,SS_CENTERIMAGE
+ CONTROL "Enabled",IDC_CHECK_DHCP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,95,77,41,10
+ CONTROL "",IDC_IPADDRESS_SUBNET,"SysIPAddress32",WS_TABSTOP,95,111,100,15
+ LTEXT "Subnet Mask:",IDC_STATIC,26,113,60,8,SS_CENTERIMAGE
+ CONTROL "",IDC_IPADDRESS_GATEWAY,"SysIPAddress32",WS_TABSTOP,95,130,100,15
+ LTEXT "Gateway Address:",IDC_STATIC,25,132,60,8,SS_CENTERIMAGE
+ CONTROL "",IDC_IPADDRESS_DNS1,"SysIPAddress32",WS_TABSTOP,95,150,100,15
+ LTEXT "DNS1 Address:",IDC_STATIC,25,152,60,8,SS_CENTERIMAGE
+ CONTROL "",IDC_IPADDRESS_DNS2,"SysIPAddress32",WS_TABSTOP,95,170,100,15
+ LTEXT "DNS2 Address:",IDC_STATIC,25,172,60,8,SS_CENTERIMAGE
+ CONTROL "Auto",IDC_CHECK_SUBNET,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,201,113,31,10
+ CONTROL "Auto",IDC_CHECK_GATEWAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,201,132,31,10
+ CONTROL "Auto",IDC_CHECK_DNS1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,201,152,31,10
+ CONTROL "Auto",IDC_CHECK_DNS2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,201,172,31,10
END
@@ -92,9 +108,9 @@ BEGIN
IDD_CONFIG, DIALOG
BEGIN
LEFTMARGIN, 7
- RIGHTMARGIN, 284
+ RIGHTMARGIN, 285
TOPMARGIN, 7
- BOTTOMMARGIN, 273
+ BOTTOMMARGIN, 314
END
END
#endif // APSTUDIO_INVOKED
diff --git a/pcsx2/DEV9/Win32/Win32.cpp b/pcsx2/DEV9/Win32/Win32.cpp
index ead67eb68e..4e060037c2 100644
--- a/pcsx2/DEV9/Win32/Win32.cpp
+++ b/pcsx2/DEV9/Win32/Win32.cpp
@@ -26,11 +26,14 @@
#include "..\DEV9.h"
#include "..\pcap_io.h"
#include "..\net.h"
+#include "..\PacketReader\IP\IP_Address.h"
#include "tap.h"
#include "AppCoreThread.h"
#include "../ATA/HddCreate.h"
+using PacketReader::IP::IP_Address;
+
extern HINSTANCE hInst;
//HANDLE handleDEV9Thread = NULL;
//DWORD dwThreadId, dwThrdParam;
@@ -47,6 +50,101 @@ void SysMessage(char* fmt, ...)
MessageBoxA(0, tmp, "Dev9 Msg", 0);
}
+void IPControl_SetValue(HWND hwndCtl, IP_Address value)
+{
+ int tmp = MAKEIPADDRESS(value.bytes[0], value.bytes[1], value.bytes[2], value.bytes[3]);
+ SendMessage(hwndCtl, IPM_SETADDRESS, (WPARAM)0, (LPARAM)tmp);
+}
+IP_Address IPControl_GetValue(HWND hwndCtl)
+{
+ int tmp;
+ SendMessage(hwndCtl, IPM_GETADDRESS, (WPARAM)0, (LPARAM)&tmp);
+ IP_Address ret;
+ ret.bytes[0] = FIRST_IPADDRESS(tmp);
+ ret.bytes[1] = SECOND_IPADDRESS(tmp);
+ ret.bytes[2] = THIRD_IPADDRESS(tmp);
+ ret.bytes[3] = FOURTH_IPADDRESS(tmp);
+ return ret;
+}
+
+void IPControl_Enable(HWND hwndCtl, bool enabled, IP_Address value)
+{
+ if (enabled)
+ {
+ EnableWindow(hwndCtl, true);
+ IPControl_SetValue(hwndCtl, value);
+ }
+ else
+ {
+ EnableWindow(hwndCtl, false);
+ IPControl_SetValue(hwndCtl, {0});
+ }
+}
+
+void AutoMaskChanged(HWND hW)
+{
+ IPControl_Enable(GetDlgItem(hW, IDC_IPADDRESS_SUBNET), !Button_GetCheck(GetDlgItem(hW, IDC_CHECK_SUBNET)), config.Mask);
+}
+
+void AutoGatewayChanged(HWND hW)
+{
+ IPControl_Enable(GetDlgItem(hW, IDC_IPADDRESS_GATEWAY), !Button_GetCheck(GetDlgItem(hW, IDC_CHECK_GATEWAY)), config.Gateway);
+}
+
+void AutoDNS1Changed(HWND hW)
+{
+ IPControl_Enable(GetDlgItem(hW, IDC_IPADDRESS_DNS1), !Button_GetCheck(GetDlgItem(hW, IDC_CHECK_DNS1)), config.DNS1);
+}
+
+void AutoDNS2Changed(HWND hW)
+{
+ IPControl_Enable(GetDlgItem(hW, IDC_IPADDRESS_DNS2), !Button_GetCheck(GetDlgItem(hW, IDC_CHECK_DNS2)), config.DNS1);
+}
+
+void InterceptChanged(HWND hW)
+{
+ if (Button_GetCheck(GetDlgItem(hW, IDC_CHECK_DHCP)))
+ {
+ EnableWindow(GetDlgItem(hW, IDC_IPADDRESS_IP), true);
+ IPControl_SetValue(GetDlgItem(hW, IDC_IPADDRESS_IP), config.PS2IP);
+
+ Button_Enable(GetDlgItem(hW, IDC_CHECK_SUBNET), true);
+ Button_Enable(GetDlgItem(hW, IDC_CHECK_GATEWAY), true);
+ Button_Enable(GetDlgItem(hW, IDC_CHECK_DNS1), true);
+ Button_Enable(GetDlgItem(hW, IDC_CHECK_DNS2), true);
+
+ Button_SetCheck(GetDlgItem(hW, IDC_CHECK_SUBNET), config.AutoMask);
+ Button_SetCheck(GetDlgItem(hW, IDC_CHECK_GATEWAY), config.AutoGateway);
+ Button_SetCheck(GetDlgItem(hW, IDC_CHECK_DNS1), config.AutoDNS1);
+ Button_SetCheck(GetDlgItem(hW, IDC_CHECK_DNS2), config.AutoDNS2);
+
+ AutoMaskChanged(hW);
+ AutoGatewayChanged(hW);
+ AutoDNS1Changed(hW);
+ AutoDNS2Changed(hW);
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hW, IDC_IPADDRESS_IP), false);
+ IPControl_SetValue(GetDlgItem(hW, IDC_IPADDRESS_IP), {0});
+
+ Button_Enable(GetDlgItem(hW, IDC_CHECK_SUBNET), false);
+ Button_Enable(GetDlgItem(hW, IDC_CHECK_GATEWAY), false);
+ Button_Enable(GetDlgItem(hW, IDC_CHECK_DNS1), false);
+ Button_Enable(GetDlgItem(hW, IDC_CHECK_DNS2), false);
+
+ Button_SetCheck(GetDlgItem(hW, IDC_CHECK_SUBNET), true);
+ Button_SetCheck(GetDlgItem(hW, IDC_CHECK_GATEWAY), true);
+ Button_SetCheck(GetDlgItem(hW, IDC_CHECK_DNS1), true);
+ Button_SetCheck(GetDlgItem(hW, IDC_CHECK_DNS2), true);
+
+ IPControl_Enable(GetDlgItem(hW, IDC_IPADDRESS_SUBNET), false, config.Mask);
+ IPControl_Enable(GetDlgItem(hW, IDC_IPADDRESS_GATEWAY), false, config.Gateway);
+ IPControl_Enable(GetDlgItem(hW, IDC_IPADDRESS_DNS1), false, config.DNS1);
+ IPControl_Enable(GetDlgItem(hW, IDC_IPADDRESS_DNS2), false, config.DNS1);
+ }
+}
+
void OnInitDialog(HWND hW)
{
//int i;
@@ -75,6 +173,9 @@ void OnInitDialog(HWND hW)
ComboBox_SetCurSel(GetDlgItem(hW, IDC_ETHDEV), itm);
}
+ Button_SetCheck(GetDlgItem(hW, IDC_CHECK_DHCP), config.InterceptDHCP);
+ InterceptChanged(hW);
+
SetWindowText(GetDlgItem(hW, IDC_HDDFILE), config.Hdd);
//HDDText
@@ -188,6 +289,28 @@ void OnOk(HWND hW)
strcpy(config.Eth, guid_char);
}
+ config.InterceptDHCP = Button_GetCheck(GetDlgItem(hW, IDC_CHECK_DHCP));
+ if (config.InterceptDHCP)
+ {
+ config.PS2IP = IPControl_GetValue(GetDlgItem(hW, IDC_IPADDRESS_IP));
+
+ config.AutoMask = Button_GetCheck(GetDlgItem(hW, IDC_CHECK_SUBNET));
+ if (!config.AutoMask)
+ config.Mask = IPControl_GetValue(GetDlgItem(hW, IDC_IPADDRESS_SUBNET));
+
+ config.AutoGateway = Button_GetCheck(GetDlgItem(hW, IDC_CHECK_GATEWAY));
+ if (!config.AutoGateway)
+ config.Gateway = IPControl_GetValue(GetDlgItem(hW, IDC_IPADDRESS_GATEWAY));
+
+ config.AutoDNS1 = Button_GetCheck(GetDlgItem(hW, IDC_CHECK_DNS1));
+ if (!config.AutoDNS1)
+ config.DNS1 = IPControl_GetValue(GetDlgItem(hW, IDC_IPADDRESS_DNS1));
+
+ config.AutoDNS2 = Button_GetCheck(GetDlgItem(hW, IDC_CHECK_DNS2));
+ if (!config.AutoDNS2)
+ config.DNS2 = IPControl_GetValue(GetDlgItem(hW, IDC_IPADDRESS_DNS2));
+ }
+
GetWindowText(GetDlgItem(hW, IDC_HDDFILE), config.Hdd, 256);
if (Edit_GetTextLength(GetDlgItem(hW, IDC_HDDSIZE_TEXT)) == 0)
@@ -259,6 +382,21 @@ BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
OnOk(hW);
return TRUE;
+ case IDC_CHECK_DHCP:
+ InterceptChanged(hW);
+ return TRUE;
+ case IDC_CHECK_SUBNET:
+ AutoMaskChanged(hW);
+ return TRUE;
+ case IDC_CHECK_GATEWAY:
+ AutoGatewayChanged(hW);
+ return TRUE;
+ case IDC_CHECK_DNS1:
+ AutoDNS1Changed(hW);
+ return TRUE;
+ case IDC_CHECK_DNS2:
+ AutoDNS2Changed(hW);
+ return TRUE;
case IDC_BROWSE:
OnBrowse(hW);
return TRUE;
diff --git a/pcsx2/DEV9/Win32/resource.h b/pcsx2/DEV9/Win32/resource.h
index b97a6095c0..ac9ef8cd23 100644
--- a/pcsx2/DEV9/Win32/resource.h
+++ b/pcsx2/DEV9/Win32/resource.h
@@ -15,6 +15,16 @@
#define IDC_HDDSIZE_SPIN 8013
#define IDC_HDDSIZE_TEXT 8015
#define IDC_BROWSE 8017
+#define IDC_IPADDRESS_IP 8018
+#define IDC_CHECK_DHCP 8019
+#define IDC_IPADDRESS_SUBNET 8020
+#define IDC_IPADDRESS_GATEWAY 8021
+#define IDC_IPADDRESS_DNS1 8022
+#define IDC_IPADDRESS_DNS2 8023
+#define IDC_CHECK_SUBNET 8024
+#define IDC_CHECK_GATEWAY 8025
+#define IDC_CHECK_DNS1 8026
+#define IDC_CHECK_DNS2 8027
#define IDC_STATIC -1
// Next default values for new objects
@@ -23,7 +33,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 806
#define _APS_NEXT_COMMAND_VALUE 40002
-#define _APS_NEXT_CONTROL_VALUE 8018
+#define _APS_NEXT_CONTROL_VALUE 8025
#define _APS_NEXT_SYMED_VALUE 801
#endif
#endif
diff --git a/pcsx2/DEV9/net.cpp b/pcsx2/DEV9/net.cpp
index bb3aac21b6..208ca0c52c 100644
--- a/pcsx2/DEV9/net.cpp
+++ b/pcsx2/DEV9/net.cpp
@@ -275,6 +275,9 @@ void NetAdapter::InitInternalServer(ifaddrs* adapter)
if (adapter == nullptr)
Console.Error("DEV9: InitInternalServer() got nullptr for adapter");
+ if (config.InterceptDHCP)
+ dhcpServer.Init(adapter);
+
if (blocks())
{
internalRxThreadRunning.store(true);
@@ -290,10 +293,26 @@ void NetAdapter::ReloadInternalServer(ifaddrs* adapter)
{
if (adapter == nullptr)
Console.Error("DEV9: ReloadInternalServer() got nullptr for adapter");
+
+ if (config.InterceptDHCP)
+ dhcpServer.Init(adapter);
}
bool NetAdapter::InternalServerRecv(NetPacket* pkt)
{
+ IP_Payload* updpkt = dhcpServer.Recv();
+ if (updpkt != nullptr)
+ {
+ IP_Packet* ippkt = new IP_Packet(updpkt);
+ ippkt->destinationIP = {255, 255, 255, 255};
+ 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;
}
@@ -305,6 +324,19 @@ bool NetAdapter::InternalServerSend(NetPacket* pkt)
PayloadPtr* payload = static_cast(frame.GetPayload());
IP_Packet ippkt(payload->data, payload->GetLength());
+ if (ippkt.protocol == (u16)IP_Type::UDP)
+ {
+ IP_PayloadPtr* ipPayload = static_cast(ippkt.GetPayload());
+ UDP_Packet udppkt(ipPayload->data, ipPayload->GetLength());
+
+ if (udppkt.destinationPort == 67)
+ {
+ //Send DHCP
+ if (config.InterceptDHCP)
+ return dhcpServer.Send(&udppkt);
+ }
+ }
+
if (ippkt.destinationIP == internalIP)
{
return true;
diff --git a/pcsx2/DEV9/net.h b/pcsx2/DEV9/net.h
index e5fa84d110..cc625a4369 100644
--- a/pcsx2/DEV9/net.h
+++ b/pcsx2/DEV9/net.h
@@ -32,6 +32,7 @@
#endif
#include "PacketReader/IP/IP_Address.h"
+#include "InternalServers/DHCP_Server.h"
struct Config;
@@ -93,6 +94,8 @@ private:
std::condition_variable internalRxCV;
bool internalRxHasData = false;
+ InternalServers::DHCP_Server dhcpServer = InternalServers::DHCP_Server([&] { InternalSignalReceived(); });
+
public:
NetAdapter();
virtual bool blocks() = 0;
diff --git a/pcsx2/windows/VCprojects/pcsx2.vcxproj b/pcsx2/windows/VCprojects/pcsx2.vcxproj
index 7ec9ca74d7..f94095a210 100644
--- a/pcsx2/windows/VCprojects/pcsx2.vcxproj
+++ b/pcsx2/windows/VCprojects/pcsx2.vcxproj
@@ -286,6 +286,7 @@
+
@@ -657,6 +658,7 @@
+
diff --git a/pcsx2/windows/VCprojects/pcsx2.vcxproj.filters b/pcsx2/windows/VCprojects/pcsx2.vcxproj.filters
index bffe0e0199..efc1b9f14a 100644
--- a/pcsx2/windows/VCprojects/pcsx2.vcxproj.filters
+++ b/pcsx2/windows/VCprojects/pcsx2.vcxproj.filters
@@ -1108,6 +1108,9 @@
System\Ps2\DEV9
+
+ System\Ps2\DEV9\InternalServers
+
System\Ps2\DEV9\PacketReader\IP\UDP\DHCP
@@ -1890,6 +1893,9 @@
System\Ps2\DEV9
+
+ System\Ps2\DEV9\InternalServers
+
System\Ps2\DEV9