diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 734d966781..7eb87d6f90 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -139,6 +139,7 @@ set(SRCS Src/ActionReplay.cpp Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp + Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.cpp Src/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.cpp Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp Src/IPC_HLE/WII_IPC_HLE_Device_usb_kbd.cpp @@ -192,7 +193,7 @@ set(SRCS Src/ActionReplay.cpp Src/PowerPC/JitCommon/JitCache.cpp Src/PowerPC/JitCommon/Jit_Util.cpp) -set(LIBS bdisasm inputcommon videoogl videosoftware sfml-network) +set(LIBS bdisasm inputcommon videoogl videosoftware sfml-network ssl) if(WIN32) set(SRCS ${SRCS} Src/HW/BBA-TAP/TAP_Win32.cpp Src/stdafx.cpp diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index 1e0561bc23..6b361b8793 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -115,7 +115,7 @@ - .\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\portaudio\include;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories) + .\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\zlib;..\..\..\Externals\openssl\$(PlatformName);%(AdditionalIncludeDirectories) true @@ -127,7 +127,7 @@ - .\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\portaudio\include;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories) + .\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\zlib;..\..\..\Externals\openssl\$(PlatformName);%(AdditionalIncludeDirectories) true @@ -139,7 +139,7 @@ - .\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\portaudio\include;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories) + .\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\zlib;..\..\..\Externals\openssl\$(PlatformName);%(AdditionalIncludeDirectories) true @@ -153,7 +153,7 @@ - .\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\portaudio\include;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories) + .\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\zlib;..\..\..\Externals\openssl\$(PlatformName);%(AdditionalIncludeDirectories) true @@ -167,7 +167,7 @@ - .\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\portaudio\include;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories) + .\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\zlib;..\..\..\Externals\openssl\$(PlatformName);%(AdditionalIncludeDirectories) true @@ -181,7 +181,7 @@ - .\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\portaudio\include;..\..\..\Externals\zlib;%(AdditionalIncludeDirectories) + .\Src;..\Common\Src;..\VideoCommon\Src;..\AudioCommon\Src;..\DiscIO\Src;..\InputCommon\Src;..\wiiuse\Src;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\SFML\include;..\..\..\Externals\LZO;..\..\..\Externals\zlib;..\..\..\Externals\openssl\$(PlatformName);%(AdditionalIncludeDirectories) true @@ -327,6 +327,7 @@ + @@ -518,6 +519,7 @@ + @@ -528,6 +530,7 @@ + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 66b25af176..e5d3df1d13 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -537,6 +537,9 @@ FifoPlayer + + IPC HLE %28IOS/Starlet%29\Net + FifoPlayer @@ -1030,8 +1033,11 @@ FifoPlayer - - HW %28Flipper/Hollywood%29\GCMemcard + + IPC HLE %28IOS/Starlet%29\Net + + + IPC HLE %28IOS/Starlet%29\Net diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp index 921d704a69..9c0991fb4f 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp @@ -46,6 +46,7 @@ They will also generate a true or false return for UpdateInterrupts() in WII_IPC #include "WII_IPC_HLE_Device_stm.h" #include "WII_IPC_HLE_Device_fs.h" #include "WII_IPC_HLE_Device_net.h" +#include "WII_IPC_HLE_Device_net_ssl.h" #include "WII_IPC_HLE_Device_es.h" #include "WII_IPC_HLE_Device_usb.h" #include "WII_IPC_HLE_Device_usb_kbd.h" @@ -91,6 +92,7 @@ void Init() g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_kd_time(i, std::string("/dev/net/kd/time")); i++; g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_ncd_manage(i, std::string("/dev/net/ncd/manage")); i++; g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_ip_top(i, std::string("/dev/net/ip/top")); i++; + g_DeviceMap[i] = new CWII_IPC_HLE_Device_net_ssl(i, std::string("/dev/net/ssl")); i++; g_DeviceMap[i] = new CWII_IPC_HLE_Device_usb_kbd(i, std::string("/dev/usb/kbd")); i++; g_DeviceMap[i] = new CWII_IPC_HLE_Device_sdio_slot0(i, std::string("/dev/sdio/slot0")); i++; g_DeviceMap[i] = new CWII_IPC_HLE_Device_stub(i, std::string("/dev/sdio/slot1")); i++; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device.h index 36709a084f..c738a5379d 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device.h @@ -93,11 +93,11 @@ public: virtual bool IsHardware() { return m_Hardware; } virtual bool IsOpened() { return m_Active; } - +public: + std::string m_Name; protected: // STATE_TO_SAVE - std::string m_Name; u32 m_DeviceID; bool m_Hardware; bool m_Active; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp index c2ed0fac36..c69ee15919 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp @@ -348,7 +348,7 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B _BufferOutSize); u32 OwnerID = 0; - u16 GroupID = 0; + u16 GroupID = 0x3031; std::string Filename = HLE_IPC_BuildFilename((const char*)Memory::GetPointer(_BufferIn), 64); u8 OwnerPerm = 0x3; // read/write u8 GroupPerm = 0x3; // read/write diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp index 75db39b994..711cd51677 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp @@ -22,19 +22,19 @@ it's used by for example SSBB, Mario Kart, Metroid Prime 3 0x01 SuspendScheduler (Input: none, Output: 32 bytes) 0x02 ExecTrySuspendScheduler (Input: 32 bytes, Output: 32 bytes) // Sounds like it will - check if it should suspend the updates scheduler or not. If I returned - (OutBuffer: 0, Ret: -1) to Metroid Prime 3 it got stuck in an endless loops of - requests, probably harmless but I changed it to (OutBuffer: 1, Ret: 0) to stop - the calls. However then it also calls 0x3 and then changes its error message - to a Wii Memory error message from just a general Error message. +check if it should suspend the updates scheduler or not. If I returned +(OutBuffer: 0, Ret: -1) to Metroid Prime 3 it got stuck in an endless loops of +requests, probably harmless but I changed it to (OutBuffer: 1, Ret: 0) to stop +the calls. However then it also calls 0x3 and then changes its error message +to a Wii Memory error message from just a general Error message. 0x03 ? (Input: none, Output: 32 bytes) // This is only called if 0x02 - does not return -1 +does not return -1 0x0f NWC24iRequestGenerateUserId (Input: none, Output: 32 bytes) Requests are made in this order by these games - Mario Kart: 2, 1, f, 3 - SSBB: 2, 3 +Mario Kart: 2, 1, f, 3 +SSBB: 2, 3 For Mario Kart I had to return -1 from at least 2, f and 3 to convince it that the network was unavailable and prevent if from looking for shared2/wc24 files (and do a PPCHalt when @@ -42,30 +42,45 @@ it failed) */ #ifdef _MSC_VER -#pragma warning(disable : 4065) // switch statement contains 'default' but no 'case' labels +#pragma warning(disable: 4748) +#pragma optimize("",off) #endif #include "WII_IPC_HLE_Device_net.h" #include "FileUtil.h" #include #include + #ifdef _WIN32 #include #include +#include + +#include "fakepoll.h" +#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) +#define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) + #elif defined(__linux__) +#include +#include #include #include #include +#include #include #include +#include #else #include #include +#include #include +#include #endif extern std::queue > g_ReplyQueueLater; - +const u8 default_address[] = { 0x00, 0x17, 0xAB, 0x99, 0x99, 0x99 }; +int status = 3; // ********************************************************************************** // Handle /dev/net/kd/request requests CWII_IPC_HLE_Device_net_kd_request::CWII_IPC_HLE_Device_net_kd_request(u32 _DeviceID, const std::string& _rDeviceName) @@ -116,14 +131,20 @@ bool CWII_IPC_HLE_Device_net_kd_request::IOCtl(u32 _CommandAddress) INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_EXEC_TRY_SUSPEND_SCHEDULAR - NI"); break; - case IOCTL_NWC24_UNK_3: // NWC24iResumeForCloseLib - INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_UNK_3 - NI"); + case IOCTL_NWC24_EXEC_RESUME_SCHEDULAR : // NWC24iResumeForCloseLib + INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_EXEC_RESUME_SCHEDULAR - NI"); break; case IOCTL_NWC24_STARTUP_SOCKET: // NWC24iStartupSocket + Memory::Write_U32(0, BufferOut); + Memory::Write_U32(0, BufferOut+4); + ReturnValue = 0; INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_STARTUP_SOCKET - NI"); break; - + case IOCTL_NWC24_CLEANUP_SOCKET: + Memory::Memset(BufferOut, 0, BufferOutSize); + INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_CLEANUP_SOCKET - NI"); + break; case IOCTL_NWC24_LOCK_SOCKET: // WiiMenu INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_LOCK_SOCKET - NI"); break; @@ -134,7 +155,11 @@ bool CWII_IPC_HLE_Device_net_kd_request::IOCtl(u32 _CommandAddress) case IOCTL_NWC24_REQUEST_GENERATED_USER_ID: // (Input: none, Output: 32 bytes) INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_REQUEST_GENERATED_USER_ID"); - memcpy(Memory::GetPointer(BufferOut), m_UserID.c_str(), m_UserID.length() + 1); + Memory::Write_U32(0xFFFFFFDC, BufferOut); + Memory::Write_U32(0x00050495, BufferOut + 4); + Memory::Write_U32(0x90CFBF35, BufferOut + 8); + Memory::Write_U32(0x00000002, BufferOut + 0xC); + //Memory::WriteBigEData((u8*)m_UserID.c_str(), BufferOut, m_UserID.length() + 1); break; case IOCTL_NWC24_GET_SCHEDULAR_STAT: @@ -178,8 +203,8 @@ CWII_IPC_HLE_Device_net_ncd_manage::CWII_IPC_HLE_Device_net_ncd_manage(u32 _Devi // wired connection on IP 192.168.1.1 using gateway 192.168.1.2 memset(&m_Ifconfig, 0, sizeof(m_Ifconfig)); - m_Ifconfig.header4 = 1; // got one "valid" connection - m_Ifconfig.header6 = 7; // this is always 7? + m_Ifconfig.connType = 1; + m_Ifconfig.linkTimeout = 7; m_Ifconfig.connection[0].flags = 167; m_Ifconfig.connection[0].ip[0] = 192; m_Ifconfig.connection[0].ip[1] = 168; @@ -188,11 +213,50 @@ CWII_IPC_HLE_Device_net_ncd_manage::CWII_IPC_HLE_Device_net_ncd_manage(u32 _Devi m_Ifconfig.connection[0].netmask[0] = 255; m_Ifconfig.connection[0].netmask[1] = 255; m_Ifconfig.connection[0].netmask[2] = 255; - m_Ifconfig.connection[0].netmask[3] = 255; + m_Ifconfig.connection[0].netmask[3] = 0; m_Ifconfig.connection[0].gateway[0] = 192; m_Ifconfig.connection[0].gateway[1] = 168; m_Ifconfig.connection[0].gateway[2] = 1; m_Ifconfig.connection[0].gateway[3] = 2; + m_Ifconfig.connection[0].dns1[0] = 10; + m_Ifconfig.connection[0].dns1[1] = 0; + m_Ifconfig.connection[0].dns1[2] = 1; + m_Ifconfig.connection[0].dns1[3] = 1; + m_Ifconfig.connection[1].flags = 167; + m_Ifconfig.connection[1].ip[0] = 192; + m_Ifconfig.connection[1].ip[1] = 168; + m_Ifconfig.connection[1].ip[2] = 1; + m_Ifconfig.connection[1].ip[3] = 1; + m_Ifconfig.connection[1].netmask[0] = 255; + m_Ifconfig.connection[1].netmask[1] = 255; + m_Ifconfig.connection[1].netmask[2] = 255; + m_Ifconfig.connection[1].netmask[3] = 0; + m_Ifconfig.connection[1].gateway[0] = 192; + m_Ifconfig.connection[1].gateway[1] = 168; + m_Ifconfig.connection[1].gateway[2] = 1; + m_Ifconfig.connection[1].gateway[3] = 2; + m_Ifconfig.connection[1].dns1[0] = 10; + m_Ifconfig.connection[1].dns1[1] = 0; + m_Ifconfig.connection[1].dns1[2] = 1; + m_Ifconfig.connection[1].dns1[3] = 1; + m_Ifconfig.connection[2].flags = 167; + m_Ifconfig.connection[2].ip[0] = 192; + m_Ifconfig.connection[2].ip[1] = 168; + m_Ifconfig.connection[2].ip[2] = 1; + m_Ifconfig.connection[2].ip[3] = 1; + m_Ifconfig.connection[2].netmask[0] = 255; + m_Ifconfig.connection[2].netmask[1] = 255; + m_Ifconfig.connection[2].netmask[2] = 255; + m_Ifconfig.connection[2].netmask[3] = 0; + m_Ifconfig.connection[2].gateway[0] = 192; + m_Ifconfig.connection[2].gateway[1] = 168; + m_Ifconfig.connection[2].gateway[2] = 1; + m_Ifconfig.connection[2].gateway[3] = 2; + m_Ifconfig.connection[2].dns1[0] = 10; + m_Ifconfig.connection[2].dns1[1] = 0; + m_Ifconfig.connection[2].dns1[2] = 1; + m_Ifconfig.connection[2].dns1[3] = 1; + } } @@ -220,117 +284,83 @@ bool CWII_IPC_HLE_Device_net_ncd_manage::Close(u32 _CommandAddress, bool _bForce bool CWII_IPC_HLE_Device_net_ncd_manage::IOCtlV(u32 _CommandAddress) { u32 ReturnValue = 0; - SIOCtlVBuffer CommandBuffer(_CommandAddress); switch (CommandBuffer.Parameter) { - case IOCTLV_NCD_READCONFIG: // 7004 out, 32 out - // first out buffer gets filled with contents of /shared2/sys/net/02/config.dat - // TODO: What's the second output buffer for? - { - INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCTLV_NCD_GETIFCONFIG"); + case IOCTLV_NCD_READCONFIG: // 7004 Out, 32 Out. 2nd, 3rd + INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCTLV_NCD_READCONFIG"); + //break; - // fill output buffer, taking care of endianness - u32 addr = CommandBuffer.PayloadBuffer.at(0).m_Address; - Memory::WriteBigEData((const u8*)&m_Ifconfig, addr, 8); - addr += 8; - for (unsigned int i = 0; i < 3; i++) + case IOCTLV_NCD_GETCONFIG: // 7004 out, 32 out + // first out buffer gets filled with contents of /shared2/sys/net/02/config.dat + // TODO: What's the second output buffer for? { - netcfg_connection_t *conn = &m_Ifconfig.connection[i]; + INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCTLV_NCD_GETCONFIG"); + u8 params1[0x1b5c]; + u8 params2[0x20]; - Memory::WriteBigEData((const u8*)conn, addr, 26); - Memory::Write_U16(Common::swap16(conn->mtu), addr+26); - Memory::WriteBigEData((const u8*)conn->padding_3, addr+28, 8); + // fill output buffer, taking care of endianness + u32 addr = CommandBuffer.PayloadBuffer.at(0).m_Address; + u32 _BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address; - Memory::WriteBigEData((const u8*)&conn->proxy_settings, addr+36, 260); - Memory::Write_U16(Common::swap16(conn->proxy_settings.proxy_port), addr+296); - Memory::WriteBigEData((const u8*)&conn->proxy_settings.proxy_username, addr+298, 65); - Memory::Write_U8(conn->padding_4, addr+363); + Memory::ReadBigEData((u8*)params1, addr, 0x1b5c); + Memory::ReadBigEData((u8*)params2, CommandBuffer.PayloadBuffer.at(1).m_Address, 0x20); - Memory::WriteBigEData((const u8*)&conn->proxy_settings_copy, addr+364, 260); - Memory::Write_U16(Common::swap16(conn->proxy_settings_copy.proxy_port), addr+624); - Memory::WriteBigEData((const u8*)&conn->proxy_settings_copy.proxy_username, addr+626, 65); - Memory::WriteBigEData((const u8*)conn->padding_5, addr+691, 1641); - addr += sizeof(netcfg_connection_t); - } - ReturnValue = 0; - break; - } - - case IOCTLV_NCD_UNK4: // 7004 In, 32 Out. 4th - INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCTLV_NCD_UNK4"); - break; - - case 0x05: // 7004 Out, 32 Out. 2nd, 3rd - INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCtlV 0x5"); - break; - - case IOCTLV_NCD_GETLINKSTATUS: // 32 Out. 5th - INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCTLV_NCD_GETLINKSTATUS"); - break; - - case IOCTLV_NCD_GETWIRELESSMACADDRESS: // 32 Out, 6 Out. 1st - // TODO: What's the first output buffer for? - // second out buffer gets filled with first four bytes of the wireless MAC address. - // No idea why the fifth and sixth bytes are left untouched. - { - // hardcoded address as a fallback - // TODO: Make this configurable? Different MAC addresses MIGHT be needed for requesting a user id or encrypting content with NWC24 - const u8 default_address[] = { 0x00, 0x19, 0x1e, 0xfd, 0x71, 0x84 }; - - INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCTLV_NCD_GETWIRELESSMACADDRESS"); - -#if defined(__linux__) - const char *check_devices[3] = { "wlan0", "ath0", "eth0" }; - int fd, ret; - struct ifreq ifr; - - fd = socket(AF_INET, SOCK_DGRAM, 0); - ifr.ifr_addr.sa_family = AF_INET; - - for (unsigned int dev = 0; dev < 3; dev++ ) - { - strncpy(ifr.ifr_name, check_devices[dev], IFNAMSIZ-1); - ret = ioctl(fd, SIOCGIFHWADDR, &ifr); - if (ret == 0) + Memory::WriteBigEData((const u8*)&m_Ifconfig, addr, 8); + addr += 8; + for (unsigned int i = 0; i < 3; i++) { - INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCTLV_NCD_GETWIRELESSMACADDRESS returning local MAC address of %s", check_devices[dev]); - Memory::WriteBigEData((const u8*)ifr.ifr_hwaddr.sa_data, CommandBuffer.PayloadBuffer.at(1).m_Address, 4); - break; + netcfg_connection_t *conn = &m_Ifconfig.connection[i]; + + Memory::WriteBigEData((const u8*)conn, addr, 26); + Memory::Write_U16(Common::swap16(conn->mtu), addr+26); + Memory::WriteBigEData((const u8*)conn->padding_3, addr+28, 8); + + Memory::WriteBigEData((const u8*)&conn->proxy_settings, addr+36, 260); + Memory::Write_U16(Common::swap16(conn->proxy_settings.proxy_port), addr+296); + Memory::WriteBigEData((const u8*)&conn->proxy_settings.proxy_username, addr+298, 65); + Memory::Write_U8(conn->padding_4, addr+363); + + Memory::WriteBigEData((const u8*)&conn->proxy_settings_copy, addr+364, 260); + Memory::Write_U16(Common::swap16(conn->proxy_settings_copy.proxy_port), addr+624); + Memory::WriteBigEData((const u8*)&conn->proxy_settings_copy.proxy_username, addr+626, 65); + Memory::WriteBigEData((const u8*)conn->padding_5, addr+691, 1641); + addr += sizeof(netcfg_connection_t); } - } - if (ret != 0) - { - // fall back to the hardcoded address - Memory::WriteBigEData(default_address, CommandBuffer.PayloadBuffer.at(1).m_Address, 4); - } - close(fd); - -#elif defined(_WIN32) - IP_ADAPTER_INFO *adapter_info = NULL; - DWORD len = 0; - - DWORD ret = GetAdaptersInfo(adapter_info, &len); - if (ret != ERROR_BUFFER_OVERFLOW || !len) - { - Memory::WriteBigEData(default_address, CommandBuffer.PayloadBuffer.at(1).m_Address, 4); + Memory::Write_U32(0, _BufferOut2); + Memory::Write_U32(0, _BufferOut2+4); + ReturnValue = 0; break; } - // LPFaint99: len is sizeof(IP_ADAPTER_INFO) * nics - 0x20 - adapter_info = new IP_ADAPTER_INFO[(len / sizeof(IP_ADAPTER_INFO)) + 1]; - ret = GetAdaptersInfo(adapter_info, &len); - - if (SUCCEEDED(ret)) Memory::WriteBigEData(adapter_info->Address, CommandBuffer.PayloadBuffer.at(1).m_Address, 4); - else Memory::WriteBigEData(default_address, CommandBuffer.PayloadBuffer.at(1).m_Address, 4); - - delete[] adapter_info; -#else - Memory::WriteBigEData(default_address, CommandBuffer.PayloadBuffer.at(1).m_Address, 4); -#endif + case IOCTLV_NCD_SETCONFIG: // 7004 In, 32 Out. 4th + u8 param1[7004]; + Memory::ReadBigEData(param1,CommandBuffer.InBuffer[0].m_Address, 100); + /*if (param1[4] == 2) + status = 3; + if (param1[4] == 1) + status = 5; + if (param1[4] == 0) + status = 2;*/ + INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCTLV_NCD_SETCONFIG"); break; - } + + case IOCTLV_NCD_GETLINKSTATUS: // 32 Out. 5th + { + INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCTLV_NCD_GETLINKSTATUS"); + Memory::Write_U32(0x00000000, CommandBuffer.PayloadBuffer[0].m_Address); + Memory::Write_U32(status, CommandBuffer.PayloadBuffer[0].m_Address+4); + break; + } + + case IOCTLV_NCD_GETWIRELESSMACADDRESS: // 32 Out, 6 Out. 1st + { + INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCTLV_NCD_GETWIRELESSMACADDRESS"); + Memory::Write_U32(0, CommandBuffer.PayloadBuffer.at(0).m_Address); + Memory::WriteBigEData(default_address, CommandBuffer.PayloadBuffer.at(1).m_Address, 6); + break; + } default: INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE IOCtlV: %#x", CommandBuffer.Parameter); @@ -346,10 +376,17 @@ bool CWII_IPC_HLE_Device_net_ncd_manage::IOCtlV(u32 _CommandAddress) CWII_IPC_HLE_Device_net_ip_top::CWII_IPC_HLE_Device_net_ip_top(u32 _DeviceID, const std::string& _rDeviceName) : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) { +#ifdef _WIN32 + int ret = WSAStartup(MAKEWORD(2,2), &InitData); + INFO_LOG(WII_IPC_NET, "WSAStartup: %d", ret); +#endif } CWII_IPC_HLE_Device_net_ip_top::~CWII_IPC_HLE_Device_net_ip_top() { +#ifdef _WIN32 + WSACleanup(); +#endif } bool CWII_IPC_HLE_Device_net_ip_top::Open(u32 _CommandAddress, u32 _Mode) @@ -377,103 +414,448 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 _CommandAddress) u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C); u32 Command = Memory::Read_U32(_CommandAddress + 0x0C); -// INFO_LOG(WII_IPC_NET,"%s - Command(0x%08x) BufferIn(0x%08x, 0x%x) BufferOut(0x%08x, 0x%x)\n", GetDeviceName().c_str(), Command, BufferIn, BufferInSize, BufferOut, BufferOutSize); - u32 ReturnValue = ExecuteCommand(Command, BufferIn, BufferInSize, BufferOut, BufferOutSize); Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); return true; } -struct bind_params { + +struct bind_params +{ u32 socket; u32 has_name; u8 name[28]; }; -struct GC_sockaddr { + +struct GC_sockaddr +{ u8 sa_len; u8 sa_family; s8 sa_data[14]; }; -struct GC_in_addr { - u32 s_addr_; // this cannot be named s_addr under windows - collides with some crazy define. + +struct GC_in_addr +{ + // this cannot be named s_addr under windows - collides with some crazy define. + u32 s_addr_; }; -struct GC_sockaddr_in { + +struct GC_sockaddr_in +{ u8 sin_len; u8 sin_family; u16 sin_port; struct GC_in_addr sin_addr; s8 sin_zero[8]; }; -u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command, u32 _BufferIn, u32 BufferInSize, u32 BufferOut, u32 BufferOutSize) -{ - // Clean the location of the output buffer to zeros as a safety precaution */ - Memory::Memset(BufferOut, 0, BufferOutSize); +#ifdef _WIN32 +char *DecodeError(int ErrorCode) +{ + static char Message[1024]; + + // If this program was multi-threaded, we'd want to use FORMAT_MESSAGE_ALLOCATE_BUFFER + // instead of a static buffer here. + // (And of course, free the buffer when we were done with it) + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, ErrorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)Message, 1024, NULL); + return Message; +} +#endif + +static int getNetErrorCode(int ret, std::string caller) +{ +#ifdef _WIN32 + INFO_LOG(WII_IPC_NET, "%s failed with error %d: %s, ret= %d\n", + caller.c_str(), WSAGetLastError(), DecodeError(WSAGetLastError()), ret); + + if (ret>= 0) + return ret; + + switch (WSAGetLastError()) + { + case 10040: + return 1; + case 10054: + return -15; + case 10035: + return -26; + case 6: + return -26; + default: + return -1; + } +#else + INFO_LOG(WII_IPC_NET, "%s failed with error %d: %s, ret= %d\n", + caller.c_str(), 0x1337, "hmm", ret); + return ret; +#endif +} + +static int inet_pton(const char *src, unsigned char *dst) +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + unsigned char tmp[4], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr(digits, ch)) != NULL) { + unsigned int newt = *tp * 10 + (pch - digits); + + if (newt > 255) + return (0); + *tp = newt; + if (! saw_digit) { + if (++octets > 4) + return (0); + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } else + return (0); + } + if (octets < 4) + return (0); + memcpy(dst, tmp, 4); + return (1); +} + + +u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command, + u32 _BufferIn, u32 BufferInSize, + u32 _BufferOut, u32 BufferOutSize) +{ switch (_Command) { case IOCTL_SO_STARTUP: + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtl request IOCTL_SO_STARTUP " + "BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + _BufferIn, BufferInSize, _BufferOut, BufferOutSize); break; + case IOCTL_SO_CONNECT: + { + //struct sockaddr_in echoServAddr; + struct connect_params{ + u32 socket; + u32 has_addr; + u8 addr[28]; + }; + struct connect_params params; + struct sockaddr_in serverAddr; + + Memory::ReadBigEData((u8*)¶ms, _BufferIn, sizeof(connect_params)); + + if (Common::swap32(params.has_addr) != 1) + return -1; + + memset(&serverAddr, 0, sizeof(serverAddr)); + memcpy(&serverAddr, params.addr, params.addr[0]); + + // GC/Wii sockets have a length param as well, we dont really care :) + serverAddr.sin_family = serverAddr.sin_family >> 8; + + int ret = connect(Common::swap32(params.socket), (struct sockaddr *) &serverAddr, sizeof(serverAddr)); + + INFO_LOG(WII_IPC_NET,"/dev/net/ip/top::IOCtl request IOCTL_SO_CONNECT (%08x, %s:%d)", + Common::swap32(params.socket), inet_ntoa(serverAddr.sin_addr), Common::swap16(serverAddr.sin_port)); + + return getNetErrorCode(ret, "SO_CONNECT"); + break; + } + + case IOCTL_SO_SHUTDOWN: + { + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtl request IOCTL_SO_SHUTDOWN " + "BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + + u32 sock = Memory::Read_U32(_BufferIn); + u32 how = Memory::Read_U32(_BufferIn+4); + int ret = shutdown(sock, how); + return getNetErrorCode(ret, "SO_SHUTDOWN"); + break; + } + + case IOCTL_SO_CLOSE: + { + u32 sock = Memory::Read_U32(_BufferIn); + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtl request IOCTL_SO_CLOSE (%08x)", sock); + + #ifdef _WIN32 + u32 ret = closesocket(sock); + + return getNetErrorCode(ret, "IOCTL_SO_CLOSE"); + #else + return close(sock); + #endif + break; + } + case IOCTL_SO_SOCKET: - { - u32 AF = Memory::Read_U32(_BufferIn); - u32 TYPE = Memory::Read_U32(_BufferIn + 0x04); - u32 PROT = Memory::Read_U32(_BufferIn + 0x04 * 2); -// u32 Unk1 = Memory::Read_U32(_BufferIn + 0x04 * 3); - u32 Socket = (u32)socket(AF, TYPE, PROT); - return Common::swap32(Socket); // So it doesn't get mangled later on - break; - } + { + u32 AF = Memory::Read_U32(_BufferIn); + u32 TYPE = Memory::Read_U32(_BufferIn + 0x04); + u32 PROT = Memory::Read_U32(_BufferIn + 0x08); + u32 s = (u32)socket(AF, TYPE, PROT); + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtl request IOCTL_SO_SOCKET " + "Socket: %08x (%d,%d,%d), BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + s, AF, TYPE, PROT, _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + return getNetErrorCode(s, "SO_SOCKET"); + break; + } case IOCTL_SO_BIND: - { - bind_params *addr = (bind_params*)Memory::GetPointer(_BufferIn); - GC_sockaddr_in addrPC; - memcpy(&addrPC, addr->name, sizeof(GC_sockaddr_in)); - sockaddr_in address; - address.sin_family = addrPC.sin_family; - address.sin_addr.s_addr = addrPC.sin_addr.s_addr_; - address.sin_port = htons(addrPC.sin_port); - int Return = bind(addr->socket, (sockaddr*)&address, sizeof(address)); - return Return; - //int bind(int s, struct sockaddr *addr, int addrlen); - break; - } + { + bind_params *addr = (bind_params*)Memory::GetPointer(_BufferIn); + GC_sockaddr_in addrPC; + memcpy(&addrPC, addr->name, sizeof(GC_sockaddr_in)); + sockaddr_in address; + address.sin_family = addrPC.sin_family; + address.sin_addr.s_addr = addrPC.sin_addr.s_addr_; + address.sin_port = addrPC.sin_port; + int ret = bind(Common::swap32(addr->socket), (sockaddr*)&address, sizeof(address)); + + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtl request IOCTL_SO_BIND (%s:%d) " + "Socket: %08X, BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + inet_ntoa(address.sin_addr), Common::swap16(address.sin_port), + Common::swap32(addr->socket), _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + + return getNetErrorCode(ret, "SO_BIND"); + break; + } case IOCTL_SO_LISTEN: - { - u32 S = Memory::Read_U32(_BufferIn); - u32 BACKLOG = Memory::Read_U32(_BufferIn + 0x04); - u32 Return = listen(S, BACKLOG); - return Return; - break; - } + { + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtl request IOCTL_SO_LISTEN " + "BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + + u32 S = Memory::Read_U32(_BufferIn); + u32 BACKLOG = Memory::Read_U32(_BufferIn + 0x04); + u32 ret = listen(S, BACKLOG); + return getNetErrorCode(ret, "SO_LISTEN"); + break; + } case IOCTL_SO_ACCEPT: - { - //TODO: (Sonic)Check if this is correct - u32 S = Memory::Read_U32(_BufferIn); - socklen_t addrlen; - struct sockaddr_in address; - u32 Return = (u32)accept(S, (struct sockaddr *)&address, &addrlen); - GC_sockaddr_in *addr = (GC_sockaddr_in*)Memory::GetPointer(BufferOut); - addr->sin_family = (u8)address.sin_family; - addr->sin_addr.s_addr_ = address.sin_addr.s_addr; - addr->sin_port = address.sin_port; - socklen_t *Len = (socklen_t *)Memory::GetPointer(BufferOut + 0x04); - *Len = addrlen; - return Return; - //int accept(int s, struct sockaddr *addr, int *addrlen); - ///dev/net/ip/top::IOCtl request 0x1 (BufferIn: (000318c0, 4), BufferOut: (00058a4c, 8) - } + { + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtl request IOCTL_SO_ACCEPT " + "BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + _BufferIn, BufferInSize, _BufferOut, BufferOutSize); - case IOCTL_SO_GETHOSTID: - return 127 << 24 | 1; + u32 S = Memory::Read_U32(_BufferIn); + struct sockaddr* addr = (struct sockaddr*) Memory::GetPointer(_BufferOut); + socklen_t* addrlen = (socklen_t*) Memory::GetPointer(BufferOutSize); + *addrlen = sizeof(struct sockaddr); + int ret = accept(S, addr, addrlen); + return getNetErrorCode(ret, "SO_ACCEPT"); + } + + case IOCTL_SO_GETSOCKOPT: + { + u32 sock = Memory::Read_U32(_BufferOut); + u32 level = Memory::Read_U32(_BufferOut + 4); + u32 optname = Memory::Read_U32(_BufferOut + 8); + u8 optval[20]; + u32 optlen = 8; + + INFO_LOG(WII_IPC_NET,"/dev/net/ip/top::IOCtl request IOCTL_SO_GETSOCKOPT " + "Socket: %08x, BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + sock, _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + + int ret = getsockopt (sock, level, optname, (char *) optval, (socklen_t*)&optlen); + Memory::Write_U32(optlen, _BufferOut + 0xC); + Memory::WriteBigEData((u8 *) optval, _BufferOut + 0x10, optlen); + return ret; + } + + case IOCTL_SO_SETSOCKOPT: + { + u32 S = Memory::Read_U32(_BufferIn); + u32 level = Memory::Read_U32(_BufferIn + 4); + u32 optname = Memory::Read_U32(_BufferIn + 8); + u32 optlen = Memory::Read_U32(_BufferIn + 0xc); + u8 optval[20]; + Memory::ReadBigEData(optval, _BufferIn + 0x10, optlen); + + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtl request IOCTL_SO_SETSOCKOPT " + "Socket: %08x, BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + S, _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + + int ret = setsockopt(S, level, optname, (char*)optval, optlen); + + return ret; + } + + case IOCTL_SO_FCNTL: + { + u32 sock = Memory::Read_U32(_BufferIn); + u32 cmd = Memory::Read_U32(_BufferIn + 4); + u32 arg = Memory::Read_U32(_BufferIn + 8); + + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtl request IOCTL_SO_FCNTL(%08X, %08X) " + "Socket: %08x, BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + cmd, arg, + sock, _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + #ifdef _WIN32 + #define F_GETFL 3 + #define F_SETFL 4 + #define F_NONBLOCK 4 + if (cmd == F_GETFL) + { + INFO_LOG(WII_IPC_NET, "F_GETFL WTF?"); + } + else if (cmd == F_SETFL) + { + u_long iMode = 0; + if (arg & F_NONBLOCK) + iMode = 1; + int ioctlret = ioctlsocket(sock, FIONBIO, &iMode); + return getNetErrorCode(ioctlret, "SO_FCNTL"); + } + else + { + INFO_LOG(WII_IPC_NET, "UNKNOWN WTF?"); + } + return 0; + #else + return fcntl(sock, cmd, arg); + #endif + } + + case IOCTL_SO_GETSOCKNAME: + { + u32 sock = Memory::Read_U32(_BufferIn); + + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtl request IOCTL_SO_GETSOCKNAME " + "Socket: %08X, BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + sock, _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + + struct sockaddr sa; + socklen_t sa_len; + sa_len = sizeof(sa); + int ret = getsockname(sock, &sa, &sa_len); + + Memory::Write_U8(BufferOutSize, _BufferOut); + Memory::Write_U8(sa.sa_family, _BufferOut+1); + Memory::WriteBigEData((u8*)&sa.sa_data, _BufferOut+2, BufferOutSize-2); + return ret; + } + + case IOCTL_SO_GETHOSTID: + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtl request IOCTL_SO_GETHOSTID " + "(BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + return 10 << 24 | 1 << 8 | 30; + + case IOCTL_SO_INETATON: + { + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtl request IOCTL_SO_INETATON " + "%s, BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + (char*)Memory::GetPointer(_BufferIn), _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + struct hostent *remoteHost = gethostbyname((char*)Memory::GetPointer(_BufferIn)); + Memory::Write_U32(Common::swap32(*(u_long *)remoteHost->h_addr_list[0]), _BufferOut); + return remoteHost->h_addr_list[0] == 0 ? -1 : 0; + } + + case IOCTL_SO_INETPTON: + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtl request IOCTL_SO_INETPTON " + "(Translating: %s)", Memory::GetPointer(_BufferIn)); + return inet_pton((char*)Memory::GetPointer(_BufferIn), Memory::GetPointer(_BufferOut+4)); break; + case IOCTL_SO_POLL: + { + #ifdef _WIN32 + u32 unknown = Memory::Read_U32(_BufferIn); + u32 timeout = Memory::Read_U32(_BufferIn + 4); + + int nfds = BufferOutSize / 0xc; + if (nfds == 0) + ERROR_LOG(WII_IPC_NET,"Hidden POLL"); + pollfd_t* ufds = (pollfd_t *)malloc(sizeof(pollfd_t) * nfds); + if (ufds == NULL) + return -1; + for (int i = 0; i < nfds; i++) + { + ufds[i].fd = Memory::Read_U32(_BufferOut + 0xc*i); + ufds[i].events = Memory::Read_U32(_BufferOut + 0xc*i + 4); + ufds[i].revents = Memory::Read_U32(_BufferOut + 0xc*i + 8); + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtl request IOCTL_SO_POLL(%d) " + "Sock: %08x, Unknown: %08x, Events: %08x, " + "BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + i, ufds[i].fd, unknown, ufds[i].events, + _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + } + int ret = poll(ufds, nfds, timeout); + for (int i = 0; ih_name, 255); + Memory::WriteBigEData((u8*)remoteHost->h_name, _BufferOut + 0x10, hnamelen); + + Memory::Write_U16(remoteHost->h_addrtype, _BufferOut + 0x8); + Memory::Write_U16(remoteHost->h_length, _BufferOut + 0xA); + Memory::Write_U32(_BufferOut + 0x340, _BufferOut + 0xC); + + for (i = 0; remoteHost->h_addr_list[i] != 0; i++) + { + u32 ip = *(u_long *)remoteHost->h_addr_list[i]; + Memory::Write_U32(_BufferOut + 0x110 + i*4 ,_BufferOut + 0x340 + i*4); + Memory::Write_U32(Common::swap32(ip), _BufferOut + 0x110 + i*4); + } + i++; + Memory::Write_U32(_BufferOut + 0x340 + i*4, _BufferOut + 0x4); + return 0; + } + else + { + return -1; + } + + break; + } + default: - INFO_LOG(WII_IPC_NET,"/dev/net/ip/top::IOCtl request 0x%x (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", - _Command, _BufferIn, BufferInSize, BufferOut, BufferOutSize); + INFO_LOG(WII_IPC_NET,"/dev/net/ip/top::IOCtl request 0x%x " + "BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + _Command, _BufferIn, BufferInSize, _BufferOut, BufferOutSize); break; } @@ -481,25 +863,358 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command, u32 _BufferIn, return 0; } +u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer CommandBuffer) +{ + u32 _BufferIn = 0, _BufferIn2 = 0, _BufferIn3 = 0; + u32 BufferInSize = 0, BufferInSize2 = 0, BufferInSize3 = 0; + + u32 _BufferOut = 0, _BufferOut2 = 0, _BufferOut3 = 0; + u32 BufferOutSize = 0, BufferOutSize2 = 0, BufferOutSize3 = 0; + + if (CommandBuffer.InBuffer.size() > 0) + { + _BufferIn = CommandBuffer.InBuffer.at(0).m_Address; + BufferInSize = CommandBuffer.InBuffer.at(0).m_Size; + } + if (CommandBuffer.InBuffer.size() > 1) + { + _BufferIn2 = CommandBuffer.InBuffer.at(1).m_Address; + BufferInSize2 = CommandBuffer.InBuffer.at(1).m_Size; + } + if (CommandBuffer.InBuffer.size() > 2) + { + _BufferIn3 = CommandBuffer.InBuffer.at(2).m_Address; + BufferInSize3 = CommandBuffer.InBuffer.at(2).m_Size; + } + + if (CommandBuffer.PayloadBuffer.size() > 0) + { + _BufferOut = CommandBuffer.PayloadBuffer.at(0).m_Address; + BufferOutSize = CommandBuffer.PayloadBuffer.at(0).m_Size; + } + if (CommandBuffer.PayloadBuffer.size() > 1) + { + _BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address; + BufferOutSize2 = CommandBuffer.PayloadBuffer.at(1).m_Size; + } + if (CommandBuffer.PayloadBuffer.size() > 2) + { + _BufferOut3 = CommandBuffer.PayloadBuffer.at(2).m_Address; + BufferOutSize3 = CommandBuffer.PayloadBuffer.at(2).m_Size; + } + + //struct ifreq { /* BUGBUG: reduced form of ifreq just for this hack */ + // char ifr_name[16]; + // struct sockaddr ifr_addr; + //}; + + //struct ifreq ifr; struct sockaddr_in saddr; + //int fd; + + #ifdef _WIN32 + PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL; + ULONG OutBufferLength = 0; + ULONG RetVal = 0, i; + #endif + + u32 param = 0, param2 = 0, param3, param4, param5 = 0; + + switch (_Parameter) + { + case IOCTLV_SO_GETINTERFACEOPT: + { + param = Memory::Read_U32(_BufferIn); + param2 = Memory::Read_U32(_BufferIn+4); + param3 = Memory::Read_U32(_BufferOut); + param4 = Memory::Read_U32(_BufferOut2); + if (BufferOutSize >= 8) + { + + param5 = Memory::Read_U32(_BufferOut+4); + } + + INFO_LOG(WII_IPC_NET,"/dev/net/ip/top::IOCtlV request IOCTLV_SO_GETINTERFACEOPT(%08X, %08X) " + "BufferIn: (%08x, %i), BufferIn2: (%08x, %i)", + param, param2, + _BufferIn, BufferInSize, _BufferIn2, BufferInSize2); + + switch (param2) + { + case 0xb003: + { + u32 address = 0; + /*fd=socket(PF_INET,SOCK_STREAM,0); + strcpy(ifr.ifr_name,"name of interface"); + ioctl(fd,SIOCGIFADDR,&ifr); + saddr=*((struct sockaddr_in *)(&(ifr.ifr_addr))); + */ + #ifdef _WIN32 + for (i = 0; i < 5; i++) + { + RetVal = GetAdaptersAddresses( + AF_INET, + 0, + NULL, + AdapterAddresses, + &OutBufferLength); + + if (RetVal != ERROR_BUFFER_OVERFLOW) { + break; + } + + if (AdapterAddresses != NULL) { + FREE(AdapterAddresses); + } + + AdapterAddresses = (PIP_ADAPTER_ADDRESSES)MALLOC(OutBufferLength); + if (AdapterAddresses == NULL) { + RetVal = GetLastError(); + break; + } + } + if (RetVal == NO_ERROR) + { + unsigned long dwBestIfIndex = 0; + IPAddr dwDestAddr = (IPAddr)0x08080808; + // If successful, output some information from the data we received + PIP_ADAPTER_ADDRESSES AdapterList = AdapterAddresses; + if (GetBestInterface(dwDestAddr,&dwBestIfIndex) == NO_ERROR) + { + while (AdapterList) + { + if (AdapterList->IfIndex == dwBestIfIndex && + AdapterList->FirstDnsServerAddress && + AdapterList->OperStatus == IfOperStatusUp) + { + INFO_LOG(WII_IPC_NET, "Name of valid interface: %S", AdapterList->FriendlyName); + INFO_LOG(WII_IPC_NET, "DNS: %u.%u.%u.%u", + (unsigned char)AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[2], + (unsigned char)AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[3], + (unsigned char)AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[5], + (unsigned char)AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[6]); + address = Common::swap32(*(u32*)(&AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[2])); + break; + } + AdapterList = AdapterList->Next; + } + } + } + if (AdapterAddresses != NULL) { + FREE(AdapterAddresses); + } + #endif + if (address == 0) + address = 0x08080808; + + Memory::Write_U32(address, _BufferOut); + Memory::Write_U32(0x08080808, _BufferOut+4); + break; + } + + case 0x1003: + Memory::Write_U32(0, _BufferOut); + break; + + case 0x1004: + Memory::WriteBigEData(default_address, _BufferOut, 6); + break; + + case 0x4002: + Memory::Write_U32(2, _BufferOut); + break; + + case 0x4003: + Memory::Write_U32(0xC, _BufferOut2); + Memory::Write_U32(10 << 24 | 1 << 8 | 30, _BufferOut); + Memory::Write_U32(255 << 24 | 255 << 16 | 255 << 8 | 0, _BufferOut+4); + Memory::Write_U32(10 << 24 | 0 << 16 | 255 << 8 | 255, _BufferOut+8); + break; + + default: + ERROR_LOG(WII_IPC_NET, "Unknown param2: %08X", param2); + break; + + } + + return 0; + break; + } + + case IOCTLV_SO_SENDTO: + { + struct sendto_params { + u32 socket; + u32 flags; + u32 has_destaddr; + u8 destaddr[28]; + }; + struct sendto_params params; + Memory::ReadBigEData((u8*)¶ms, _BufferIn2, BufferInSize2); + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtlV request IOCTLV_SO_SENDTO " + "Socket: %08x, BufferIn: (%08x, %i), BufferIn2: (%08x, %i)", + Common::swap32(params.socket), _BufferIn, BufferInSize, _BufferIn2, BufferInSize2); + + if (params.has_destaddr) + { + struct sockaddr_in* addr = (struct sockaddr_in*)¶ms.destaddr; + u8 len = sizeof(sockaddr); //addr->sin_family & 0xFF; + addr->sin_family = addr->sin_family >> 8; + int ret = sendto(Common::swap32(params.socket), (char*)Memory::GetPointer(_BufferIn), + BufferInSize, Common::swap32(params.flags), (struct sockaddr*)addr, len); + return getNetErrorCode(ret, "SO_SENDTO"); + } + else + { + int ret = send(Common::swap32(params.socket), (char*)Memory::GetPointer(_BufferIn), + BufferInSize, Common::swap32(params.flags)); + return getNetErrorCode(ret, "SO_SEND"); + } + break; + } + + case IOCTLV_SO_RECVFROM: + { + u32 sock = Memory::Read_U32(_BufferIn); + u32 flags = Memory::Read_U32(_BufferIn + 4); + + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtlV request IOCTLV_SO_RECVFROM " + "Socket: %08X, Flags: %08X, " + "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " + "BufferOut: (%08x, %i), BufferOut2: (%08x, %i)", + sock, flags, + _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, + _BufferOut, BufferOutSize, _BufferOut2, BufferOutSize2); + + char *buf = (char *)Memory::GetPointer(_BufferOut); + int len = BufferOutSize; + struct sockaddr_in addr; + socklen_t fromlen = 0; + + if (_BufferOut2 != 0) + { + fromlen = BufferOutSize2 >= sizeof(struct sockaddr) ? BufferOutSize2 : sizeof(struct sockaddr); + } + + if (flags != 2) + flags = 0; + else + flags = MSG_PEEK; + + + int ret = recvfrom(sock, buf, len, flags, + fromlen ? (struct sockaddr*) &addr : NULL, fromlen ? &fromlen : NULL); + if (_BufferOut2 != 0) + { + addr.sin_family = (addr.sin_family << 8) | (BufferOutSize2&0xFF); + Memory::WriteBigEData((u8*)&addr, _BufferOut2, BufferOutSize2); + } + return getNetErrorCode(ret, "SO_RECVFROM"); + break; + } + + case IOCTLV_SO_GETADDRINFO: + { + struct addrinfo hints; + struct addrinfo *result = NULL; + + if (BufferInSize3) + { + hints.ai_flags = Memory::Read_U32(_BufferIn3); + hints.ai_family = Memory::Read_U32(_BufferIn3 + 0x4); + hints.ai_socktype = Memory::Read_U32(_BufferIn3 + 0x8); + hints.ai_protocol = Memory::Read_U32(_BufferIn3 + 0xC); + hints.ai_addrlen = Memory::Read_U32(_BufferIn3 + 0x10); + hints.ai_canonname = (char*)Memory::Read_U32(_BufferIn3 + 0x14); + hints.ai_addr = (sockaddr *)Memory::Read_U32(_BufferIn3 + 0x18); + hints.ai_next = (addrinfo *)Memory::Read_U32(_BufferIn3 + 0x1C); + } + + char* pNodeName = NULL; + if (BufferInSize > 0) + pNodeName = (char*)Memory::GetPointer(_BufferIn); + + char* pServiceName = NULL; + if (BufferInSize2 > 0) + pServiceName = (char*)Memory::GetPointer(_BufferIn2); + + int ret = getaddrinfo(pNodeName, pServiceName, &hints, &result); + u32 addr = _BufferOut; + u32 sockoffset = addr + 0x460; + if (ret >= 0) + { + while (result != NULL) + { + Memory::Write_U32(result->ai_flags, addr); + Memory::Write_U32(result->ai_family, addr + 0x04); + Memory::Write_U32(result->ai_socktype, addr + 0x08); + Memory::Write_U32(result->ai_protocol, addr + 0x0C); + Memory::Write_U32(result->ai_addrlen, addr + 0x10); + // what to do? where to put? the buffer of 0x834 doesn't allow space for this + Memory::Write_U32(/*result->ai_cannonname*/ 0, addr + 0x14); + + if (result->ai_addr) + { + Memory::Write_U32(sockoffset, addr + 0x18); + Memory::Write_U16(((result->ai_addr->sa_family & 0xFF) << 8) | (result->ai_addrlen & 0xFF), sockoffset); + Memory::WriteBigEData((u8*)result->ai_addr->sa_data, sockoffset + 0x2, sizeof(result->ai_addr->sa_data)); + sockoffset += 0x1C; + } + else + { + Memory::Write_U32(0, addr + 0x18); + } + + if (result->ai_next) + { + Memory::Write_U32(addr + sizeof(addrinfo), addr + 0x1C); + } + else + { + Memory::Write_U32(0, addr + 0x1C); + } + + addr += sizeof(addrinfo); + result = result->ai_next; + } + } + + INFO_LOG(WII_IPC_NET, "/dev/net/ip/top::IOCtlV request IOCTLV_SO_GETADDRINFO " + "(BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + INFO_LOG(WII_IPC_NET, "IOCTLV_SO_GETADDRINFO: %s", Memory::GetPointer(_BufferIn)); + return ret; + } + + default: + INFO_LOG(WII_IPC_NET,"/dev/net/ip/top::IOCtlV request 0x%x (BufferIn: (%08x, %i), BufferIn2: (%08x, %i)", + _Parameter, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2); + break; + + } + return 0; +} + bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 _CommandAddress) { u32 ReturnValue = 0; - SIOCtlVBuffer CommandBuffer(_CommandAddress); switch (CommandBuffer.Parameter) { - case IOCTL_SO_BIND: - case IOCTLV_SO_RECVFROM: - case IOCTL_SO_SOCKET: - case IOCTL_SO_GETHOSTID: - case IOCTL_SO_STARTUP: - //break; - - default: - INFO_LOG(WII_IPC_NET, "NET_IP_TOP IOCtlV: 0x%08X\n", CommandBuffer.Parameter); - break; + case IOCTLV_SO_SENDTO: + case IOCTL_SO_BIND: + case IOCTLV_SO_RECVFROM: + case IOCTL_SO_SOCKET: + case IOCTL_SO_GETHOSTID: + case IOCTL_SO_STARTUP: + default: + ReturnValue = ExecuteCommandV(CommandBuffer.Parameter, CommandBuffer); + break; } Memory::Write_U32(ReturnValue, _CommandAddress+4); return true; } + +#ifdef _MSC_VER +#pragma optimize("",on) +#endif diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.h index 29769e5b85..739a3d7780 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.h @@ -18,12 +18,22 @@ #ifndef _WII_IPC_HLE_DEVICE_NET_H_ #define _WII_IPC_HLE_DEVICE_NET_H_ +#ifdef _MSC_VER +#pragma warning(disable: 4748) +#pragma optimize("",off) +#endif + #include "WII_IPC_HLE_Device.h" +#ifdef _WIN32 +#include +#endif + + // data layout of the network configuration file (/shared2/sys/net/02/config.dat) // needed for /dev/net/ncd/manage #pragma pack(1) -typedef struct +struct netcfg_proxy_t { u8 use_proxy; // 0x00 -> no proxy; 0x01 -> proxy u8 use_proxy_userandpass; // 0x00 -> don't use username and password; 0x01 -> use username and password @@ -34,9 +44,9 @@ typedef struct u8 proxy_username[32]; u8 padding_3; u8 proxy_password[32]; -} netcfg_proxy_t; +}; -typedef struct +struct netcfg_connection_t { // settings common to both wired and wireless connections u8 flags; // Connection selected @@ -87,27 +97,24 @@ typedef struct u8 key[64]; // encryption key; for WEP, key is stored 4 times (20 bytes for WEP64 and 52 bytes for WEP128) then padded with 0x00 u8 padding_12[236]; -} netcfg_connection_t; +}; -typedef struct +struct network_config_t { - u8 header0; // 0x00 - u8 header1; // 0x00 - u8 header2; // 0x00 - u8 header3; // 0x00 - u8 header4; // 0x01 if there's at least one valid connection to the Internet. - u8 header5; // 0x00 - u8 header6; // always 0x07? - u8 header7; // 0x00 + u32 version; + u8 connType; // 0x01 if there's at least one valid connection to the Internet. + u8 nwc24Permission; // 0x00 + u8 linkTimeout; // always 0x07? + u8 padding; // 0x00 netcfg_connection_t connection[3]; -} network_config_t; +}; #pragma pack() -// ********************************************************************************** -// KD is the IOS module responsible for implementing WiiConnect24 functionality. It -// can perform HTTPS downloads, send and receive mail via SMTP, and execute a +////////////////////////////////////////////////////////////////////////// +// KD is the IOS module responsible for implementing WiiConnect24 functionality. +// It can perform HTTPS downloads, send and receive mail via SMTP, and execute a // JavaScript-like language while the Wii is in standby mode. class CWII_IPC_HLE_Device_net_kd_request : public IWII_IPC_HLE_Device { @@ -125,24 +132,24 @@ private: { IOCTL_NWC24_SUSPEND_SCHEDULAR = 0x01, IOCTL_NWC24_EXEC_TRY_SUSPEND_SCHEDULAR = 0x02, - IOCTL_NWC24_UNK_3 = 0x03, - IOCTL_NWC24_UNK_4 = 0x04, + IOCTL_NWC24_EXEC_RESUME_SCHEDULAR = 0x03, + IOCTL_NWC24_KD_GET_TIME_TRIGGERS = 0x04, IOCTL_NWC24_UNK_5 = 0x05, IOCTL_NWC24_STARTUP_SOCKET = 0x06, IOCTL_NWC24_CLEANUP_SOCKET = 0x07, IOCTL_NWC24_LOCK_SOCKET = 0x08, IOCTL_NWC24_UNLOCK_SOCKET = 0x09, - IOCTL_NWC24_UNK_A = 0x0A, - IOCTL_NWC24_UNK_B = 0x0B, - IOCTL_NWC24_UNK_C = 0x0C, + IOCTL_NWC24_CHECK_MAIL_NOW = 0x0A, + IOCTL_NWC24_SEND_MAIL_NOW = 0x0B, + IOCTL_NWC24_RECEIVE_MAIL_NOW = 0x0C, IOCTL_NWC24_SAVE_MAIL_NOW = 0x0D, IOCTL_NWC24_DOWNLOAD_NOW_EX = 0x0E, IOCTL_NWC24_REQUEST_GENERATED_USER_ID = 0x0F, IOCTL_NWC24_REQUEST_REGISTER_USER_ID = 0x10, IOCTL_NWC24_GET_SCHEDULAR_STAT = 0x1E, - IOCTL_NWC24_UNK_1F = 0x1F, - IOCTL_NWC24_UNK_20 = 0x20, - IOCTL_NWC24_UNK_21 = 0x21, + IOCTL_NWC24_SET_FILTER_MODE = 0x1F, + IOCTL_NWC24_SET_DEBUG_MODE = 0x20, + IOCTL_NWC24_KD_SET_NEXT_WAKEUP = 0x21, IOCTL_NWC24_SET_SCRIPT_MODE = 0x22, IOCTL_NWC24_REQUEST_SHUTDOWN = 0x28, }; @@ -151,13 +158,16 @@ private: std::string m_UserID; }; -// ********************************************************************************** +////////////////////////////////////////////////////////////////////////// class CWII_IPC_HLE_Device_net_kd_time : public IWII_IPC_HLE_Device { + u64 timediff; public: - CWII_IPC_HLE_Device_net_kd_time(u32 _DeviceID, const std::string& _rDeviceName) : - IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) - {} + CWII_IPC_HLE_Device_net_kd_time(u32 _DeviceID, const std::string& _rDeviceName) + : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) + { + timediff = 1337; // this must be stored somewhere? + } virtual ~CWII_IPC_HLE_Device_net_kd_time() {} @@ -188,26 +198,29 @@ public: switch (Parameter) { case IOCTL_NW24_SET_RTC_COUNTER: // NWC24iSetRtcCounter (but prolly just the first 4 bytes are intresting...) + { _dbg_assert_msg_(WII_IPC_NET, BufferInSize==0x20, "NET_KD_TIME: Set RTC Counter BufferIn to small"); _dbg_assert_msg_(WII_IPC_NET, BufferOutSize==0x20, "NET_KD_TIME: Set RTC Counter BufferOut to small"); - - for (int i=0; i<0x20; i++) - { - m_RtcCounter[i] = Memory::Read_U8(BufferIn+i); - } - - // send back for sync?? at least there is a out buffer... - for (int i=0; i<0x20; i++) - { - Memory::Write_U8(m_RtcCounter[i], BufferOut+i); - } - + u64 rtctime = Memory::Read_U64(BufferIn+4); + Memory::Write_U32(0, BufferOut); + Memory::Write_U64(rtctime + timediff, BufferOut+4); + INFO_LOG(WII_IPC_NET, "NET_KD_TIME: Set RTC Counter"); Memory::Write_U32(0, _CommandAddress + 0x4); return true; + } + + case IOCTL_NW24_GET_TIME_DIFF: + { + Memory::Write_U32(0, BufferOut); + Memory::Write_U64(timediff, BufferOut+4); + INFO_LOG(WII_IPC_NET, "NET_KD_TIME: Get time diff"); + + Memory::Write_U32(0, _CommandAddress + 0x4); + return true; + } - case IOCTL_NW24_GET_TIME_DIFF: // Input: none, Output: 32 default: ERROR_LOG(WII_IPC_NET, "%s - IOCtl:\n" " Parameter: 0x%x (0x17 NWC24iSetRtcCounter) \n" @@ -234,7 +247,7 @@ private: u8 m_RtcCounter[0x20]; }; -// ********************************************************************************** +////////////////////////////////////////////////////////////////////////// class CWII_IPC_HLE_Device_net_ip_top : public IWII_IPC_HLE_Device { public: @@ -248,7 +261,12 @@ public: virtual bool IOCtlV(u32 _CommandAddress); private: - enum { +#ifdef _WIN32 + WSADATA InitData; +#endif + + enum + { IOCTL_SO_ACCEPT = 1, IOCTL_SO_BIND, IOCTL_SO_CLOSE, @@ -287,6 +305,7 @@ private: }; u32 ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _BufferInSize, u32 _BufferOut, u32 _BufferOutSize); + u32 ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer CommandBuffer); }; // ********************************************************************************** @@ -303,16 +322,23 @@ public: virtual bool IOCtlV(u32 _CommandAddress); private: - enum { - IOCTLV_NCD_UNK1 = 0x1, // NCDLockWirelessDriver - IOCTLV_NCD_UNK2 = 0x2, // NCDUnlockWirelessDriver - IOCTLV_NCD_READCONFIG = 0x3, // NCDReadConfig? - IOCTLV_NCD_UNK4 = 0x4, - IOCTLV_NCD_GETLINKSTATUS = 0x7, // NCDGetLinkStatus - IOCTLV_NCD_GETWIRELESSMACADDRESS = 0x8, // NCDGetWirelessMacAddress + enum + { + IOCTLV_NCD_LOCKWIRELESSDRIVER = 0x1, // NCDLockWirelessDriver + IOCTLV_NCD_UNLOCKWIRELESSDRIVER = 0x2, // NCDUnlockWirelessDriver + IOCTLV_NCD_GETCONFIG = 0x3, // NCDiGetConfig + IOCTLV_NCD_SETCONFIG = 0x4, // NCDiSetConfig + IOCTLV_NCD_READCONFIG = 0x5, + IOCTLV_NCD_WRITECONFIG = 0x6, + IOCTLV_NCD_GETLINKSTATUS = 0x7, // NCDGetLinkStatus + IOCTLV_NCD_GETWIRELESSMACADDRESS = 0x8, // NCDGetWirelessMacAddress }; network_config_t m_Ifconfig; }; +#ifdef _MSC_VER +#pragma optimize("",on) +#endif + #endif diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.cpp new file mode 100644 index 0000000000..7e59eb715a --- /dev/null +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.cpp @@ -0,0 +1,467 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program 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 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifdef _MSC_VER +#pragma warning(disable: 4748) +#pragma optimize("",off) +#endif + +#include +#include "FileUtil.h" +#include "WII_IPC_HLE_Device_net_ssl.h" + +CWII_IPC_HLE_Device_net_ssl::CWII_IPC_HLE_Device_net_ssl(u32 _DeviceID, const std::string& _rDeviceName) + : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) +{ + SSL_library_init(); + sslfds[0] = NULL; + sslfds[1] = NULL; + sslfds[2] = NULL; + sslfds[3] = NULL; +} + +CWII_IPC_HLE_Device_net_ssl::~CWII_IPC_HLE_Device_net_ssl() +{ +} + +int CWII_IPC_HLE_Device_net_ssl::getSSLFreeID() +{ + for (int i = 0; i < NET_SSL_MAXINSTANCES; i++) + { + if (sslfds[i] == NULL) + return i + 1; + } + return 0; +} +bool CWII_IPC_HLE_Device_net_ssl::Open(u32 _CommandAddress, u32 _Mode) +{ + Memory::Write_U32(GetDeviceID(), _CommandAddress+4); + m_Active = true; + return true; +} + +bool CWII_IPC_HLE_Device_net_ssl::Close(u32 _CommandAddress, bool _bForce) +{ + if (!_bForce) + Memory::Write_U32(0, _CommandAddress + 4); + m_Active = false; + return true; +} + +bool CWII_IPC_HLE_Device_net_ssl::IOCtl(u32 _CommandAddress) +{ + u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10); + u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14); + u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); + u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C); + u32 Command = Memory::Read_U32(_CommandAddress + 0x0C); + + u32 ReturnValue = ExecuteCommand(Command, BufferIn, BufferInSize, BufferOut, BufferOutSize); + Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); + return true; +} + +bool CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress) +{ + u32 ReturnValue = 0; + SIOCtlVBuffer CommandBuffer(_CommandAddress); + + ReturnValue = ExecuteCommandV(CommandBuffer.Parameter, CommandBuffer); + + Memory::Write_U32(ReturnValue, _CommandAddress+4); + return true; +} + +u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer CommandBuffer) +{ + u32 returnValue = 0; + + u32 _BufferIn = 0, _BufferIn2 = 0, _BufferIn3 = 0; + u32 BufferInSize = 0, BufferInSize2 = 0, BufferInSize3 = 0; + + u32 _BufferOut = 0, _BufferOut2 = 0, _BufferOut3 = 0; + u32 BufferOutSize = 0, BufferOutSize2 = 0, BufferOutSize3 = 0; + + if (CommandBuffer.InBuffer.size() > 0) + { + _BufferIn = CommandBuffer.InBuffer.at(0).m_Address; + BufferInSize = CommandBuffer.InBuffer.at(0).m_Size; + } + if (CommandBuffer.InBuffer.size() > 1) + { + _BufferIn2 = CommandBuffer.InBuffer.at(1).m_Address; + BufferInSize2 = CommandBuffer.InBuffer.at(1).m_Size; + } + if (CommandBuffer.InBuffer.size() > 2) + { + _BufferIn3 = CommandBuffer.InBuffer.at(2).m_Address; + BufferInSize3 = CommandBuffer.InBuffer.at(2).m_Size; + } + + if (CommandBuffer.PayloadBuffer.size() > 0) + { + _BufferOut = CommandBuffer.PayloadBuffer.at(0).m_Address; + BufferOutSize = CommandBuffer.PayloadBuffer.at(0).m_Size; + } + if (CommandBuffer.PayloadBuffer.size() > 1) + { + _BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address; + BufferOutSize2 = CommandBuffer.PayloadBuffer.at(1).m_Size; + } + if (CommandBuffer.PayloadBuffer.size() > 2) + { + _BufferOut3 = CommandBuffer.PayloadBuffer.at(2).m_Address; + BufferOutSize3 = CommandBuffer.PayloadBuffer.at(2).m_Size; + } + + switch (_Parameter) + { + case IOCTLV_NET_SSL_NEW: + { + char in1[32]; + char out1[32]; + char out2[256]; + + Memory::ReadBigEData((u8*)in1, _BufferIn, 32); + Memory::ReadBigEData((u8*)out1, _BufferOut, 32); + Memory::ReadBigEData((u8*)out2, _BufferOut2, 256); + + int freeSSL = this->getSSLFreeID(); + if (freeSSL) + { + Memory::Write_U32(freeSSL, _BufferIn); + + SSL_CTX* ctx = SSL_CTX_new(SSLv23_method()); + + //SSL_CTX_set_options(ctx,0); + + SSL* ssl = SSL_new(ctx); + sslfds[freeSSL-1] = ssl; + + } + + INFO_LOG(WII_IPC_NET, "/dev/net/ssl::IOCtlV request IOCTLV_NET_SSL_NEW " + "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " + "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " + "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", + _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, + _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, + _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + break; + } + + case IOCTLV_NET_SSL_SHUTDOWN: + { + char in1[32]; + char out1[32]; + Memory::ReadBigEData((u8*)in1, _BufferIn, 32); + Memory::ReadBigEData((u8*)out1, _BufferOut, 32); + int sslID = Memory::Read_U32(_BufferOut) - 1; + if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL) + { + SSL_CTX* ctx = sslfds[sslID]->ctx; + SSL_shutdown(sslfds[sslID]); + if (ctx) + SSL_CTX_free(ctx); + sslfds[sslID] = NULL; + Memory::Write_U32(0, _BufferIn); + } + INFO_LOG(WII_IPC_NET, "/dev/net/ssl::IOCtlV request IOCTLV_NET_SSL_SHUTDOWN " + "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " + "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " + "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", + _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, + _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, + _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + break; + } + + case IOCTLV_NET_SSL_SETBUILTINCLIENTCERT: + { + INFO_LOG(WII_IPC_NET, "/dev/net/ssl::IOCtlV request IOCTLV_NET_SSL_SETBUILTINCLIENTCERT " + "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " + "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " + "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", + _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, + _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, + _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + + char in1[32]; + char out1[32]; + char out2[32]; + Memory::ReadBigEData((u8*)in1, _BufferIn, 32); + Memory::ReadBigEData((u8*)out1, _BufferOut, 32); + Memory::ReadBigEData((u8*)out2, _BufferOut2, 32); + int sslID = Memory::Read_U32(_BufferOut) - 1; + if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL) + { + SSL* ssl = sslfds[sslID]; + + std::string cert_base_path(File::GetUserPath(D_WIIUSER_IDX)); + FILE * clientca = fopen((cert_base_path + "clientca.cer").c_str(), "rb"); + if (clientca == NULL) + break; + + X509 *cert = d2i_X509_fp(clientca, NULL); + fclose(clientca); + + FILE * clientcakey = fopen((cert_base_path + "clientcakey.der").c_str(), "rb"); + if (clientcakey == NULL) + break; + + + EVP_PKEY * key = d2i_PrivateKey_fp(clientcakey, NULL); + + + if (SSL_use_certificate(ssl,cert) <= 0) + break; + if (SSL_use_PrivateKey(ssl,key) <= 0) + break; + + + if (!SSL_check_private_key(ssl)) + break; + + if (cert) + X509_free(cert); + if (key) + EVP_PKEY_free(key); + + /*PKCS12 *p12; + + FILE* f = fopen("c:\\wii_retail.p12", "rb"); + + if (!f) + break; + + + p12 = d2i_PKCS12_fp(f, NULL); + fclose(f); + if (!p12) + break; + EVP_PKEY *pkey = NULL; + X509 *cert = NULL; + STACK_OF(X509) *ca = sk_X509_new_null(); + + PKCS12_PBE_add(); + + if (!PKCS12_parse(p12, "", &pkey, &cert, &ca)) + break; + + if (cert) { + SSL_CTX_use_certificate(ssl->ctx, cert); + X509_free(cert); + } + if (pkey) +{ + SSL_CTX_use_PrivateKey(ssl->ctx, pkey); + EVP_PKEY_free(pkey); + } + + + for (int i = 0; i < sk_X509_num(ca); i++) { + X509 *cert2 = sk_X509_value(ca, i); + + char buf[200]; + + X509_NAME_oneline(X509_get_subject_name(cert2), buf, sizeof(buf)); + SSL_CTX_add_extra_chain_cert(ssl->ctx, cert2); + + } + sk_X509_free(ca); + + PKCS12_free(p12); + */ + + //SSL_CTX_use_certificate_chain_file(ssl->ctx, (char*)ssl->cert); + Memory::Write_U32(0, _BufferIn); + } + break; + } + + case IOCTLV_NET_SSL_SETBUILTINROOTCA: + { + char in1[32]; + char out1[32]; + char out2[32]; + Memory::ReadBigEData((u8*)in1, _BufferIn, 32); + Memory::ReadBigEData((u8*)out1, _BufferOut, 32); + Memory::ReadBigEData((u8*)out2, _BufferOut2, 32); + int sslID = Memory::Read_U32(_BufferOut) - 1; + if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL) +{ + + Memory::Write_U32(0, _BufferIn); + } + INFO_LOG(WII_IPC_NET, "/dev/net/ssl::IOCtlV request IOCTLV_NET_SSL_SETBUILTINROOTCA " + "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " + "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " + "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", + _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, + _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, + _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + break; + } + + case IOCTLV_NET_SSL_CONNECT: + { + char in1[32]; + char out1[32]; + char out2[32]; + Memory::ReadBigEData((u8*)in1, _BufferIn, 32); + Memory::ReadBigEData((u8*)out1, _BufferOut, 32); + Memory::ReadBigEData((u8*)out2, _BufferOut2, 32); + int sslID = Memory::Read_U32(_BufferOut) - 1; + if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL) + { + int sock = Memory::Read_U32(_BufferOut2); + SSL* ssl = sslfds[sslID]; + SSL_set_fd(ssl,sock); + returnValue = SSL_connect(ssl); + Memory::Write_U32(0, _BufferIn); + } + INFO_LOG(WII_IPC_NET, "/dev/net/ssl::IOCtlV request IOCTLV_NET_SSL_CONNECT " + "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " + "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " + "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", + _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, + _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, + _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + break; + } + + case IOCTLV_NET_SSL_DOHANDSHAKE: + { + char in1[32]; + char out1[32]; + Memory::ReadBigEData((u8*)in1, _BufferIn, 32); + Memory::ReadBigEData((u8*)out1, _BufferOut, 32); + + int sslID = Memory::Read_U32(_BufferOut) - 1; + if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL) + { + SSL* ssl = sslfds[sslID]; + returnValue = SSL_do_handshake(ssl); + if (returnValue == 1) + Memory::Write_U32(0, _BufferIn); + } + INFO_LOG(WII_IPC_NET, "/dev/net/ssl::IOCtlV request IOCTLV_NET_SSL_DOHANDSHAKE " + "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " + "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " + "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", + _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, + _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, + _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + break; + } + + case IOCTLV_NET_SSL_WRITE: + { + char in1[32]; + char out1[32]; + char out2[256]; + + Memory::ReadBigEData((u8*)in1, _BufferIn, 32); + Memory::ReadBigEData((u8*)out1, _BufferOut, 32); + Memory::ReadBigEData((u8*)out2, _BufferOut2, 256); + + int sslID = Memory::Read_U32(_BufferOut) - 1; + if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL) + { + SSL* ssl = sslfds[sslID]; + returnValue = SSL_write(ssl, Memory::GetPointer(_BufferOut2), BufferOutSize2); + Memory::Write_U32(returnValue, _BufferIn); + returnValue = 0; + } + INFO_LOG(WII_IPC_NET, "/dev/net/ssl::IOCtlV request IOCTLV_NET_SSL_WRITE " + "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " + "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " + "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", + _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, + _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, + _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + INFO_LOG(WII_IPC_NET, "%s", Memory::GetPointer(_BufferOut2)); + break; + } + + case IOCTLV_NET_SSL_READ: + { + char in1[32]; + char in2[256]; + char out1[32]; + memset(in2, 0, 256); + Memory::ReadBigEData((u8*)in1, _BufferIn, 32); + //Memory::ReadBigEData((u8*)in2, _BufferIn2, BufferInSize2); + Memory::ReadBigEData((u8*)out1, _BufferOut, 32); + + int sslID = Memory::Read_U32(_BufferOut) - 1; + if (sslID >= 0 && sslID < NET_SSL_MAXINSTANCES && sslfds[sslID] != NULL) + { + SSL* ssl = sslfds[sslID]; + returnValue = SSL_read(ssl, Memory::GetPointer(_BufferIn2), BufferInSize2); + Memory::Write_U32(returnValue, _BufferIn); + //returnValue = 0; + } + strncpy(in2, (char*)Memory::GetPointer(_BufferIn2), BufferInSize2); + INFO_LOG(WII_IPC_NET, "/dev/net/ssl::IOCtlV request IOCTLV_NET_SSL_READ(%d) %s " + "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " + "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " + "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", + returnValue, in2, + _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, + _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, + _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + break; + } + + default: + { + INFO_LOG(WII_IPC_NET, "/dev/net/ssl::IOCtlV request %x " + "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), " + "BufferIn3: (%08x, %i), BufferOut: (%08x, %i), " + "BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)", + _Parameter, + _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, + _BufferIn3, BufferInSize3, _BufferOut, BufferOutSize, + _BufferOut2, BufferOutSize2, _BufferOut3, BufferOutSize3); + break; + } + } + return returnValue; +} + +u32 CWII_IPC_HLE_Device_net_ssl::ExecuteCommand(u32 _Command, + u32 _BufferIn, u32 BufferInSize, + u32 _BufferOut, u32 BufferOutSize) +{ + switch (_Command) + { + default: + { + INFO_LOG(WII_IPC_NET, "/dev/net/ssl::IOCtl request %x " + "(BufferIn: (%08x, %i), BufferOut: (%08x, %i)", + _Command, + _BufferIn, BufferInSize, _BufferOut, BufferOutSize); + break; + } + } + return 0; +} + +#ifdef _MSC_VER +#pragma optimize("",on) +#endif diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.h new file mode 100644 index 0000000000..156892d0d5 --- /dev/null +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net_ssl.h @@ -0,0 +1,82 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program 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 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _WII_IPC_HLE_DEVICE_NET_SSL_H_ +#define _WII_IPC_HLE_DEVICE_NET_SSL_H_ + +#ifdef _MSC_VER +#pragma warning(disable: 4748) +#pragma optimize("",off) +#endif + +#include "WII_IPC_HLE_Device.h" +#include +#include +#include +#include + +#define NET_SSL_MAXINSTANCES 4 + +class CWII_IPC_HLE_Device_net_ssl : public IWII_IPC_HLE_Device +{ +public: + + CWII_IPC_HLE_Device_net_ssl(u32 _DeviceID, const std::string& _rDeviceName); + + virtual ~CWII_IPC_HLE_Device_net_ssl(); + + virtual bool Open(u32 _CommandAddress, u32 _Mode); + + virtual bool Close(u32 _CommandAddress, bool _bForce); + + virtual bool IOCtl(u32 _CommandAddress); + virtual bool IOCtlV(u32 _CommandAddress); + int getSSLFreeID(); + +private: + SSL * sslfds[NET_SSL_MAXINSTANCES]; + enum + { + IOCTLV_NET_SSL_NEW = 0x01, + IOCTLV_NET_SSL_CONNECT = 0x02, + IOCTLV_NET_SSL_DOHANDSHAKE = 0x03, + IOCTLV_NET_SSL_READ = 0x04, + IOCTLV_NET_SSL_WRITE = 0x05, + IOCTLV_NET_SSL_SHUTDOWN = 0x06, + IOCTLV_NET_SSL_SETCLIENTCERT = 0x07, + IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT = 0x08, + IOCTLV_NET_SSL_REMOVECLIENTCERT = 0x09, + IOCTLV_NET_SSL_SETROOTCA = 0x0A, + IOCTLV_NET_SSL_SETROOTCADEFAULT = 0x0B, + IOCTLV_NET_SSL_DOHANDSHAKEEX = 0x0C, + IOCTLV_NET_SSL_SETBUILTINROOTCA = 0x0D, + IOCTLV_NET_SSL_SETBUILTINCLIENTCERT = 0x0E, + IOCTLV_NET_SSL_DISABLEVERIFYOPTIONFORDEBUG = 0x0F, + IOCTLV_NET_SSL_DEBUGGETVERSION = 0x14, + IOCTLV_NET_SSL_DEBUGGETTIME = 0x15, + }; + + + u32 ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _BufferInSize, u32 _BufferOut, u32 _BufferOutSize); + u32 ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer CommandBuffer); +}; + +#ifdef _MSC_VER +#pragma optimize("",off) +#endif + +#endif diff --git a/Source/Core/Core/Src/IPC_HLE/fakepoll.h b/Source/Core/Core/Src/IPC_HLE/fakepoll.h new file mode 100644 index 0000000000..25bf123567 --- /dev/null +++ b/Source/Core/Core/Src/IPC_HLE/fakepoll.h @@ -0,0 +1,178 @@ +// fakepoll.h +// poll using select +//Matthew Parlane sourced this from http://www.sealiesoftware.com/ +//Was listed as "Public domain." as of 31/07/2010 + +// Warning: a call to this poll() takes about 4K of stack space. + +// Greg Parker gparker-web@sealiesoftware.com December 2000 +// This code is in the public domain and may be copied or modified without +// permission. + +// Updated May 2002: +// * fix crash when an fd is less than 0 +// * set errno=EINVAL if an fd is greater or equal to FD_SETSIZE +// * don't set POLLIN or POLLOUT in revents if it wasn't requested +// in events (only happens when an fd is in the poll set twice) + +#if (_WIN32_WINNT < _WIN32_WINNT_VISTA) + +#ifndef _FAKE_POLL_H +#define _FAKE_POLL_H + +#ifdef _MSC_VER +#pragma warning(disable: 4748) +#pragma optimize("",off) +#endif + +#include +#include +#include + +typedef struct pollfd { + int fd; /* file desc to poll */ + short events; /* events of interest on fd */ + short revents; /* events that occurred on fd */ +} pollfd_t; + +#define EINVAL 22 +// poll flags +#define POLLIN 0x0001 +#define POLLOUT 0x0008 +#define POLLERR 0x0040 + +// synonyms +#define POLLNORM POLLIN +#define POLLPRI POLLIN +#define POLLRDNORM POLLIN +#define POLLRDBAND POLLIN +#define POLLWRNORM POLLOUT +#define POLLWRBAND POLLOUT + +// ignored +#define POLLHUP 0x0010 +#define POLLNVAL 0x0020 + +inline int poll(struct pollfd *pollSet, int pollCount, int pollTimeout) +{ + struct timeval tv; + struct timeval *tvp; + fd_set readFDs, writeFDs, exceptFDs; + fd_set *readp, *writep, *exceptp; + struct pollfd *pollEnd, *p; + int selected; + int result; + int maxFD; + + if (!pollSet) { + pollEnd = NULL; + readp = NULL; + writep = NULL; + exceptp = NULL; + maxFD = 0; + } + else { + pollEnd = pollSet + pollCount; + readp = &readFDs; + writep = &writeFDs; + exceptp = &exceptFDs; + + FD_ZERO(readp); + FD_ZERO(writep); + FD_ZERO(exceptp); + + // Find the biggest fd in the poll set + maxFD = 0; + for (p = pollSet; p < pollEnd; p++) { + if (p->fd > maxFD) maxFD = p->fd; + } + + // Transcribe flags from the poll set to the fd sets + for (p = pollSet; p < pollEnd; p++) { + if (p->fd < 0) { + // Negative fd checks nothing and always reports zero + } else { + if (p->events & POLLIN) FD_SET(p->fd, readp); + if (p->events & POLLOUT) FD_SET(p->fd, writep); + if (p->events != 0) FD_SET(p->fd, exceptp); + // POLLERR is never set coming in; poll() always reports errors + // But don't report if we're not listening to anything at all. + } + } + } + + // poll timeout is in milliseconds. Convert to struct timeval. + // poll timeout == -1 : wait forever : select timeout of NULL + // poll timeout == 0 : return immediately : select timeout of zero + if (pollTimeout >= 0) { + tv.tv_sec = pollTimeout / 1000; + tv.tv_usec = (pollTimeout % 1000) * 1000; + tvp = &tv; + } else { + tvp = NULL; + } + + + selected = select(maxFD+1, readp, writep, exceptp, tvp); + + + if (selected < 0) { + // Error during select + result = -1; + } + else if (selected > 0) { + // Select found something + // Transcribe result from fd sets to poll set. + // Also count the number of selected fds. poll returns the + // number of ready fds; select returns the number of bits set. + int polled = 0; + for (p = pollSet; p < pollEnd; p++) { + p->revents = 0; + if (p->fd < 0) { + // Negative fd always reports zero + } else { + int isToRead = FD_ISSET(p->fd, readp); + if ((p->events & POLLIN) && isToRead) { + p->revents |= POLLIN; + } + + int isToWrite = FD_ISSET(p->fd, writep); + if ((p->events & POLLOUT) && isToWrite) { + p->revents |= POLLOUT; + } + + int isToError = FD_ISSET(p->fd, exceptp); + if ((p->events != 0) && isToError) { + p->revents |= POLLERR; + } + + if (p->revents) polled++; + } + } + result = polled; + } + else { + // selected == 0, select timed out before anything happened + // Clear all result bits and return zero. + for (p = pollSet; p < pollEnd; p++) { + p->revents = 0; + + } + result = 0; + } + return result; +} + +#ifdef _MSC_VER +#pragma optimize("",on) +#endif + + +#endif + +#else // (_WIN32_WINNT < _WIN32_WINNT_VISTA) + +typedef pollfd pollfd_t; +#define poll WSAPoll + +#endif diff --git a/Source/VSProps/CodeGen_Debug.props b/Source/VSProps/CodeGen_Debug.props index 9c321b75aa..ea95e744b7 100644 --- a/Source/VSProps/CodeGen_Debug.props +++ b/Source/VSProps/CodeGen_Debug.props @@ -10,6 +10,9 @@ Disabled false + + libeay32d.lib;ssleay32d.lib;%(AdditionalDependencies) + \ No newline at end of file diff --git a/Source/VSProps/CodeGen_DebugFast.props b/Source/VSProps/CodeGen_DebugFast.props index dc534c6a85..d6203032d3 100644 --- a/Source/VSProps/CodeGen_DebugFast.props +++ b/Source/VSProps/CodeGen_DebugFast.props @@ -11,6 +11,9 @@ MultiThreaded false + + libeay32.lib;ssleay32.lib;%(AdditionalDependencies) + \ No newline at end of file diff --git a/Source/VSProps/CodeGen_Release.props b/Source/VSProps/CodeGen_Release.props index 74770b6910..df94824093 100644 --- a/Source/VSProps/CodeGen_Release.props +++ b/Source/VSProps/CodeGen_Release.props @@ -24,6 +24,7 @@ true true + libeay32.lib;ssleay32.lib;%(AdditionalDependencies) diff --git a/Source/VSProps/Dolphin.Win32.props b/Source/VSProps/Dolphin.Win32.props index 8908f84c94..fead4baff9 100644 --- a/Source/VSProps/Dolphin.Win32.props +++ b/Source/VSProps/Dolphin.Win32.props @@ -7,7 +7,7 @@ - ..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\Cg;..\..\..\Externals\portaudio\$(PlatformName) + ..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\Cg;..\..\..\Externals\portaudio\$(PlatformName);..\..\..\Externals\openssl\$(PlatformName) portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;cg.lib;cgGL.lib;opengl32.lib;glew32s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;%(AdditionalDependencies) diff --git a/Source/VSProps/Dolphin.x64.props b/Source/VSProps/Dolphin.x64.props index b729ff4414..336fd2c1c4 100644 --- a/Source/VSProps/Dolphin.x64.props +++ b/Source/VSProps/Dolphin.x64.props @@ -8,7 +8,7 @@ - ..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\Cg64;..\..\..\Externals\portaudio\$(PlatformName) + ..\..\..\Externals\SDL\$(PlatformName);..\..\..\Externals\GLew;..\..\..\Externals\Cg64;..\..\..\Externals\portaudio\$(PlatformName);..\..\..\Externals\openssl\$(PlatformName) portaudio.lib;dsound.lib;dxerr.lib;iphlpapi.lib;winmm.lib;setupapi.lib;xinput.lib;vfw32.lib;cg.lib;cgGL.lib;opengl32.lib;glew64s.lib;glu32.lib;rpcrt4.lib;comctl32.lib;%(AdditionalDependencies)