From 3d1b79464cb02ea2e6ebb927cbf2429c65a3faeb Mon Sep 17 00:00:00 2001 From: TheLastRar Date: Mon, 8 Mar 2021 15:26:12 +0000 Subject: [PATCH] DEV9: Add internal DHCP Server --- pcsx2/CMakeLists.txt | 2 + pcsx2/DEV9/DEV9.h | 11 + pcsx2/DEV9/InternalServers/DHCP_Server.cpp | 497 ++++++++++++++++++ pcsx2/DEV9/InternalServers/DHCP_Server.h | 86 +++ pcsx2/DEV9/Linux/Config.cpp | 88 +++- pcsx2/DEV9/Linux/Linux.cpp | 127 +++++ pcsx2/DEV9/Linux/dev9.ui | 208 ++++++++ pcsx2/DEV9/Win32/DEV9WinConfig.cpp | 56 +- pcsx2/DEV9/Win32/DEV9ghzdrk.rc | 50 +- pcsx2/DEV9/Win32/Win32.cpp | 138 +++++ pcsx2/DEV9/Win32/resource.h | 12 +- pcsx2/DEV9/net.cpp | 32 ++ pcsx2/DEV9/net.h | 3 + pcsx2/windows/VCprojects/pcsx2.vcxproj | 2 + .../windows/VCprojects/pcsx2.vcxproj.filters | 6 + 15 files changed, 1290 insertions(+), 28 deletions(-) create mode 100644 pcsx2/DEV9/InternalServers/DHCP_Server.cpp create mode 100644 pcsx2/DEV9/InternalServers/DHCP_Server.h 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 True False + start Ethernet Device: @@ -133,6 +135,212 @@ 0 + + + True + False + start + Intercept DHCP: + + + 0 + 1 + + + + + Enabled + True + True + False + True + + + + 1 + 1 + 2 + + + + + True + False + start + PS2 Address: + + + 0 + 2 + + + + + True + False + start + Subnet Mask: + + + 0 + 3 + + + + + True + False + start + Gateway Address: + + + 0 + 4 + + + + + True + False + start + DNS1 Address: + + + 0 + 5 + + + + + True + False + start + DNS2 Address: + + + 0 + 6 + + + + + True + True + 15 + 0.0.0.0 + + + 1 + 2 + + + + + True + True + 15 + 0.0.0.0 + + + 1 + 3 + + + + + True + True + 15 + 0.0.0.0 + + + 1 + 4 + + + + + True + True + 15 + 0.0.0.0 + + + 1 + 5 + + + + + True + True + 15 + 0.0.0.0 + + + 1 + 6 + + + + + Auto + True + True + False + True + + + + 2 + 3 + + + + + Auto + True + True + False + True + + + + 2 + 4 + + + + + Auto + True + True + False + True + + + + 2 + 5 + + + + + Auto + True + True + False + True + + + + 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