| File: | Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp |
| Location: | line 93, column 6 |
| Description: | Value stored to 'BufferOutSize' during its initialization is never read |
| 1 | // Copyright 2013 Dolphin Emulator Project |
| 2 | // Licensed under GPLv2 |
| 3 | // Refer to the license.txt file included. |
| 4 | |
| 5 | |
| 6 | /* |
| 7 | The /dev/net/kd/request requests are part of what is called WiiConnect24, |
| 8 | it's used by for example SSBB, Mario Kart, Metroid Prime 3 |
| 9 | |
| 10 | 0x01 SuspendScheduler (Input: none, Output: 32 bytes) |
| 11 | 0x02 ExecTrySuspendScheduler (Input: 32 bytes, Output: 32 bytes) // Sounds like it will |
| 12 | check if it should suspend the updates scheduler or not. If I returned |
| 13 | (OutBuffer: 0, Ret: -1) to Metroid Prime 3 it got stuck in an endless loops of |
| 14 | requests, probably harmless but I changed it to (OutBuffer: 1, Ret: 0) to stop |
| 15 | the calls. However then it also calls 0x3 and then changes its error message |
| 16 | to a Wii Memory error message from just a general Error message. |
| 17 | |
| 18 | 0x03 ? (Input: none, Output: 32 bytes) // This is only called if 0x02 |
| 19 | does not return -1 |
| 20 | 0x0f NWC24iRequestGenerateUserId (Input: none, Output: 32 bytes) |
| 21 | |
| 22 | Requests are made in this order by these games |
| 23 | Mario Kart: 2, 1, f, 3 |
| 24 | SSBB: 2, 3 |
| 25 | |
| 26 | For Mario Kart I had to return -1 from at least 2, f and 3 to convince it that the network |
| 27 | was unavailable and prevent if from looking for shared2/wc24 files (and do a PPCHalt when |
| 28 | it failed) |
| 29 | */ |
| 30 | |
| 31 | #ifdef _MSC_VER |
| 32 | #pragma warning(disable : 4065) // switch statement contains 'default' but no 'case' labels |
| 33 | #endif |
| 34 | |
| 35 | #include "WII_IPC_HLE_Device_net.h" |
| 36 | #include "../ConfigManager.h" |
| 37 | #include "FileUtil.h" |
| 38 | #include <stdio.h> |
| 39 | #include <string> |
| 40 | #ifdef _WIN32 |
| 41 | #include <ws2tcpip.h> |
| 42 | #include <iphlpapi.h> |
| 43 | #elif defined(__linux__1) |
| 44 | #include <sys/types.h> |
| 45 | #include <sys/socket.h> |
| 46 | #include <sys/ioctl.h> |
| 47 | #include <netinet/in.h> |
| 48 | #include <net/if.h> |
| 49 | #else |
| 50 | #include <sys/types.h> |
| 51 | #include <sys/socket.h> |
| 52 | #include <netinet/in.h> |
| 53 | #endif |
| 54 | |
| 55 | extern std::queue<std::pair<u32,std::string> > g_ReplyQueueLater; |
| 56 | |
| 57 | // ********************************************************************************** |
| 58 | // Handle /dev/net/kd/request requests |
| 59 | CWII_IPC_HLE_Device_net_kd_request::CWII_IPC_HLE_Device_net_kd_request(u32 _DeviceID, const std::string& _rDeviceName) |
| 60 | : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) |
| 61 | , m_UserID("Dolphin-EMU") |
| 62 | // TODO: Dump the true ID from real Wii |
| 63 | { |
| 64 | } |
| 65 | |
| 66 | CWII_IPC_HLE_Device_net_kd_request::~CWII_IPC_HLE_Device_net_kd_request() |
| 67 | { |
| 68 | } |
| 69 | |
| 70 | bool CWII_IPC_HLE_Device_net_kd_request::Open(u32 _CommandAddress, u32 _Mode) |
| 71 | { |
| 72 | INFO_LOG(WII_IPC_NET, "NET_KD_REQ: Open")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 72, "NET_KD_REQ: Open"); } } while (0); |
| 73 | Memory::Write_U32(GetDeviceID(), _CommandAddress + 4); |
| 74 | m_Active = true; |
| 75 | return true; |
| 76 | } |
| 77 | |
| 78 | bool CWII_IPC_HLE_Device_net_kd_request::Close(u32 _CommandAddress, bool _bForce) |
| 79 | { |
| 80 | INFO_LOG(WII_IPC_NET, "NET_KD_REQ: Close")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 80, "NET_KD_REQ: Close"); } } while (0); |
| 81 | if (!_bForce) |
| 82 | Memory::Write_U32(0, _CommandAddress + 4); |
| 83 | m_Active = false; |
| 84 | return true; |
| 85 | } |
| 86 | |
| 87 | bool CWII_IPC_HLE_Device_net_kd_request::IOCtl(u32 _CommandAddress) |
| 88 | { |
| 89 | u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC); |
| 90 | u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10); |
| 91 | u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14); |
| 92 | u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); |
| 93 | u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C); |
Value stored to 'BufferOutSize' during its initialization is never read | |
| 94 | |
| 95 | u32 ReturnValue = 0; |
| 96 | switch (Parameter) |
| 97 | { |
| 98 | case IOCTL_NWC24_SUSPEND_SCHEDULAR: |
| 99 | // NWC24iResumeForCloseLib from NWC24SuspendScheduler (Input: none, Output: 32 bytes) |
| 100 | INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_SUSPEND_SCHEDULAR - NI")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 100, "NET_KD_REQ: IOCTL_NWC24_SUSPEND_SCHEDULAR - NI"); } } while (0); |
| 101 | break; |
| 102 | |
| 103 | case IOCTL_NWC24_EXEC_TRY_SUSPEND_SCHEDULAR: // NWC24iResumeForCloseLib |
| 104 | INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_EXEC_TRY_SUSPEND_SCHEDULAR - NI")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 104, "NET_KD_REQ: IOCTL_NWC24_EXEC_TRY_SUSPEND_SCHEDULAR - NI" ); } } while (0); |
| 105 | break; |
| 106 | |
| 107 | case IOCTL_NWC24_UNK_3: // NWC24iResumeForCloseLib |
| 108 | INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_UNK_3 - NI")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 108, "NET_KD_REQ: IOCTL_NWC24_UNK_3 - NI"); } } while (0); |
| 109 | break; |
| 110 | |
| 111 | case IOCTL_NWC24_STARTUP_SOCKET: // NWC24iStartupSocket |
| 112 | INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_STARTUP_SOCKET - NI")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 112, "NET_KD_REQ: IOCTL_NWC24_STARTUP_SOCKET - NI"); } } while (0); |
| 113 | break; |
| 114 | |
| 115 | case IOCTL_NWC24_LOCK_SOCKET: // WiiMenu |
| 116 | INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_LOCK_SOCKET - NI")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 116, "NET_KD_REQ: IOCTL_NWC24_LOCK_SOCKET - NI"); } } while (0); |
| 117 | break; |
| 118 | |
| 119 | case IOCTL_NWC24_UNLOCK_SOCKET: |
| 120 | INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_UNLOCK_SOCKET - NI")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 120, "NET_KD_REQ: IOCTL_NWC24_UNLOCK_SOCKET - NI"); } } while (0); |
| 121 | break; |
| 122 | |
| 123 | case IOCTL_NWC24_REQUEST_GENERATED_USER_ID: // (Input: none, Output: 32 bytes) |
| 124 | INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_REQUEST_GENERATED_USER_ID")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 124, "NET_KD_REQ: IOCTL_NWC24_REQUEST_GENERATED_USER_ID"); } } while (0); |
| 125 | memcpy(Memory::GetPointer(BufferOut), m_UserID.c_str(), m_UserID.length() + 1); |
| 126 | break; |
| 127 | |
| 128 | case IOCTL_NWC24_GET_SCHEDULAR_STAT: |
| 129 | INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_GET_SCHEDULAR_STAT - NI")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 129, "NET_KD_REQ: IOCTL_NWC24_GET_SCHEDULAR_STAT - NI"); } } while (0); |
| 130 | break; |
| 131 | |
| 132 | case IOCTL_NWC24_SAVE_MAIL_NOW: |
| 133 | INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_SAVE_MAIL_NOW - NI")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 133, "NET_KD_REQ: IOCTL_NWC24_SAVE_MAIL_NOW - NI"); } } while (0); |
| 134 | break; |
| 135 | |
| 136 | case IOCTL_NWC24_REQUEST_SHUTDOWN: |
| 137 | // if ya set the IOS version to a very high value this happens ... |
| 138 | INFO_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_REQUEST_SHUTDOWN - NI")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 138, "NET_KD_REQ: IOCTL_NWC24_REQUEST_SHUTDOWN - NI"); } } while (0); |
| 139 | break; |
| 140 | |
| 141 | default: |
| 142 | INFO_LOG(WII_IPC_NET, "/dev/net/kd/request::IOCtl request 0x%x (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 143, "/dev/net/kd/request::IOCtl request 0x%x (BufferIn: (%08x, %i), BufferOut: (%08x, %i)" , Parameter, BufferIn, BufferInSize, BufferOut, BufferOutSize ); } } while (0) |
| 143 | Parameter, BufferIn, BufferInSize, BufferOut, BufferOutSize)do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 143, "/dev/net/kd/request::IOCtl request 0x%x (BufferIn: (%08x, %i), BufferOut: (%08x, %i)" , Parameter, BufferIn, BufferInSize, BufferOut, BufferOutSize ); } } while (0); |
| 144 | break; |
| 145 | } |
| 146 | |
| 147 | // g_ReplyQueueLater.push(std::pair<u32, std::string>(_CommandAddress, GetDeviceName())); |
| 148 | Memory::Write_U32(ReturnValue, _CommandAddress + 4); |
| 149 | |
| 150 | return true; |
| 151 | } |
| 152 | |
| 153 | |
| 154 | // ********************************************************************************** |
| 155 | // Handle /dev/net/ncd/manage requests |
| 156 | CWII_IPC_HLE_Device_net_ncd_manage::CWII_IPC_HLE_Device_net_ncd_manage(u32 _DeviceID, const std::string& _rDeviceName) |
| 157 | : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) |
| 158 | { |
| 159 | // store network configuration |
| 160 | const std::string filename(File::GetUserPath(D_WIIUSER_IDX) + "shared2/sys/net/02/config.dat"); |
| 161 | |
| 162 | File::IOFile file(filename, "rb"); |
| 163 | if (!file.ReadBytes(&m_Ifconfig, 1)) |
| 164 | { |
| 165 | INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: Failed to load /shared2/sys/net/02/config.dat, using dummy configuration")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 165, "NET_NCD_MANAGE: Failed to load /shared2/sys/net/02/config.dat, using dummy configuration" ); } } while (0); |
| 166 | |
| 167 | // wired connection on IP 192.168.1.1 using gateway 192.168.1.2 |
| 168 | memset(&m_Ifconfig, 0, sizeof(m_Ifconfig)); |
| 169 | m_Ifconfig.header4 = 1; // got one "valid" connection |
| 170 | m_Ifconfig.header6 = 7; // this is always 7? |
| 171 | m_Ifconfig.connection[0].flags = 167; |
| 172 | m_Ifconfig.connection[0].ip[0] = 192; |
| 173 | m_Ifconfig.connection[0].ip[1] = 168; |
| 174 | m_Ifconfig.connection[0].ip[2] = 1; |
| 175 | m_Ifconfig.connection[0].ip[3] = 1; |
| 176 | m_Ifconfig.connection[0].netmask[0] = 255; |
| 177 | m_Ifconfig.connection[0].netmask[1] = 255; |
| 178 | m_Ifconfig.connection[0].netmask[2] = 255; |
| 179 | m_Ifconfig.connection[0].netmask[3] = 255; |
| 180 | m_Ifconfig.connection[0].gateway[0] = 192; |
| 181 | m_Ifconfig.connection[0].gateway[1] = 168; |
| 182 | m_Ifconfig.connection[0].gateway[2] = 1; |
| 183 | m_Ifconfig.connection[0].gateway[3] = 2; |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | CWII_IPC_HLE_Device_net_ncd_manage::~CWII_IPC_HLE_Device_net_ncd_manage() |
| 188 | { |
| 189 | } |
| 190 | |
| 191 | bool CWII_IPC_HLE_Device_net_ncd_manage::Open(u32 _CommandAddress, u32 _Mode) |
| 192 | { |
| 193 | INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: Open")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 193, "NET_NCD_MANAGE: Open"); } } while (0); |
| 194 | Memory::Write_U32(GetDeviceID(), _CommandAddress+4); |
| 195 | m_Active = true; |
| 196 | return true; |
| 197 | } |
| 198 | |
| 199 | bool CWII_IPC_HLE_Device_net_ncd_manage::Close(u32 _CommandAddress, bool _bForce) |
| 200 | { |
| 201 | INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: Close")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 201, "NET_NCD_MANAGE: Close"); } } while (0); |
| 202 | if (!_bForce) |
| 203 | Memory::Write_U32(0, _CommandAddress + 4); |
| 204 | m_Active = false; |
| 205 | return true; |
| 206 | } |
| 207 | |
| 208 | bool CWII_IPC_HLE_Device_net_ncd_manage::IOCtlV(u32 _CommandAddress) |
| 209 | { |
| 210 | u32 ReturnValue = 0; |
| 211 | |
| 212 | SIOCtlVBuffer CommandBuffer(_CommandAddress); |
| 213 | |
| 214 | switch (CommandBuffer.Parameter) |
| 215 | { |
| 216 | case IOCTLV_NCD_READCONFIG: // 7004 out, 32 out |
| 217 | // first out buffer gets filled with contents of /shared2/sys/net/02/config.dat |
| 218 | // TODO: What's the second output buffer for? |
| 219 | { |
| 220 | INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCTLV_NCD_GETIFCONFIG")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 220, "NET_NCD_MANAGE: IOCTLV_NCD_GETIFCONFIG"); } } while ( 0); |
| 221 | |
| 222 | // fill output buffer, taking care of endianness |
| 223 | u32 addr = CommandBuffer.PayloadBuffer.at(0).m_Address; |
| 224 | Memory::WriteBigEData((const u8*)&m_Ifconfig, addr, 8); |
| 225 | addr += 8; |
| 226 | for (unsigned int i = 0; i < 3; i++) |
| 227 | { |
| 228 | netcfg_connection_t *conn = &m_Ifconfig.connection[i]; |
| 229 | |
| 230 | Memory::WriteBigEData((const u8*)conn, addr, 26); |
| 231 | Memory::Write_U16(Common::swap16(conn->mtu), addr+26); |
| 232 | Memory::WriteBigEData((const u8*)conn->padding_3, addr+28, 8); |
| 233 | |
| 234 | Memory::WriteBigEData((const u8*)&conn->proxy_settings, addr+36, 260); |
| 235 | Memory::Write_U16(Common::swap16(conn->proxy_settings.proxy_port), addr+296); |
| 236 | Memory::WriteBigEData((const u8*)&conn->proxy_settings.proxy_username, addr+298, 65); |
| 237 | Memory::Write_U8(conn->padding_4, addr+363); |
| 238 | |
| 239 | Memory::WriteBigEData((const u8*)&conn->proxy_settings_copy, addr+364, 260); |
| 240 | Memory::Write_U16(Common::swap16(conn->proxy_settings_copy.proxy_port), addr+624); |
| 241 | Memory::WriteBigEData((const u8*)&conn->proxy_settings_copy.proxy_username, addr+626, 65); |
| 242 | Memory::WriteBigEData((const u8*)conn->padding_5, addr+691, 1641); |
| 243 | addr += sizeof(netcfg_connection_t); |
| 244 | } |
| 245 | ReturnValue = 0; |
| 246 | break; |
| 247 | } |
| 248 | |
| 249 | case IOCTLV_NCD_UNK4: // 7004 In, 32 Out. 4th |
| 250 | INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCTLV_NCD_UNK4")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 250, "NET_NCD_MANAGE: IOCTLV_NCD_UNK4"); } } while (0); |
| 251 | break; |
| 252 | |
| 253 | case 0x05: // 7004 Out, 32 Out. 2nd, 3rd |
| 254 | INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCtlV 0x5")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 254, "NET_NCD_MANAGE: IOCtlV 0x5"); } } while (0); |
| 255 | break; |
| 256 | |
| 257 | case IOCTLV_NCD_GETLINKSTATUS: // 32 Out. 5th |
| 258 | INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCTLV_NCD_GETLINKSTATUS")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 258, "NET_NCD_MANAGE: IOCTLV_NCD_GETLINKSTATUS"); } } while (0); |
| 259 | break; |
| 260 | |
| 261 | case IOCTLV_NCD_GETWIRELESSMACADDRESS: // 32 Out, 6 Out. 1st |
| 262 | // TODO: What's the first output buffer for? |
| 263 | // second out buffer gets filled with first four bytes of the wireless MAC address. |
| 264 | // No idea why the fifth and sixth bytes are left untouched. |
| 265 | { |
| 266 | // hardcoded address as a fallback |
| 267 | const u8 default_address[] = { 0x00, 0x19, 0x1e, 0xfd, 0x71, 0x84 }; |
| 268 | |
| 269 | INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCTLV_NCD_GETWIRELESSMACADDRESS")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 269, "NET_NCD_MANAGE: IOCTLV_NCD_GETWIRELESSMACADDRESS"); } } while (0); |
| 270 | |
| 271 | if (!SConfig::GetInstance().m_WirelessMac.empty()) |
| 272 | { |
| 273 | int x = 0; |
| 274 | int tmpaddress[6]; |
| 275 | for (unsigned int i = 0; i < SConfig::GetInstance().m_WirelessMac.length() && x < 6; i++) |
| 276 | { |
| 277 | if (SConfig::GetInstance().m_WirelessMac[i] == ':' || SConfig::GetInstance().m_WirelessMac[i] == '-') |
| 278 | continue; |
| 279 | |
| 280 | std::stringstream ss; |
| 281 | ss << std::hex << SConfig::GetInstance().m_WirelessMac[i]; |
| 282 | if (SConfig::GetInstance().m_WirelessMac[i+1] != ':' && SConfig::GetInstance().m_WirelessMac[i+1] != '-') |
| 283 | { |
| 284 | ss << std::hex << SConfig::GetInstance().m_WirelessMac[i+1]; |
| 285 | i++; |
| 286 | } |
| 287 | ss >> tmpaddress[x]; |
| 288 | x++; |
| 289 | } |
| 290 | u8 address[6]; |
| 291 | for (int i = 0; i < 6;i++) |
| 292 | address[i] = tmpaddress[i]; |
| 293 | Memory::WriteBigEData(address, CommandBuffer.PayloadBuffer.at(1).m_Address, 4); |
| 294 | break; |
| 295 | } |
| 296 | |
| 297 | #if defined(__linux__1) |
| 298 | const char *check_devices[3] = { "wlan0", "ath0", "eth0" }; |
| 299 | int fd, ret; |
| 300 | struct ifreq ifr; |
| 301 | |
| 302 | fd = socket(AF_INET2, SOCK_DGRAMSOCK_DGRAM, 0); |
| 303 | ifr.ifr_addrifr_ifru.ifru_addr.sa_family = AF_INET2; |
| 304 | |
| 305 | for (unsigned int dev = 0; dev < 3; dev++ ) |
| 306 | { |
| 307 | strncpy(ifr.ifr_nameifr_ifrn.ifrn_name, check_devices[dev], IFNAMSIZ16-1); |
| 308 | ret = ioctl(fd, SIOCGIFHWADDR0x8927, &ifr); |
| 309 | if (ret == 0) |
| 310 | { |
| 311 | INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE: IOCTLV_NCD_GETWIRELESSMACADDRESS returning local MAC address of %s", check_devices[dev])do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 311, "NET_NCD_MANAGE: IOCTLV_NCD_GETWIRELESSMACADDRESS returning local MAC address of %s" , check_devices[dev]); } } while (0); |
| 312 | Memory::WriteBigEData((const u8*)ifr.ifr_hwaddrifr_ifru.ifru_hwaddr.sa_data, CommandBuffer.PayloadBuffer.at(1).m_Address, 4); |
| 313 | break; |
| 314 | } |
| 315 | } |
| 316 | if (ret != 0) |
| 317 | { |
| 318 | // fall back to the hardcoded address |
| 319 | Memory::WriteBigEData(default_address, CommandBuffer.PayloadBuffer.at(1).m_Address, 4); |
| 320 | } |
| 321 | close(fd); |
| 322 | |
| 323 | #elif defined(_WIN32) |
| 324 | IP_ADAPTER_INFO *adapter_info = NULL__null; |
| 325 | DWORD len = 0; |
| 326 | |
| 327 | DWORD ret = GetAdaptersInfo(adapter_info, &len); |
| 328 | if (ret != ERROR_BUFFER_OVERFLOW || !len) |
| 329 | { |
| 330 | Memory::WriteBigEData(default_address, CommandBuffer.PayloadBuffer.at(1).m_Address, 4); |
| 331 | break; |
| 332 | } |
| 333 | |
| 334 | // LPFaint99: len is sizeof(IP_ADAPTER_INFO) * nics - 0x20 |
| 335 | adapter_info = new IP_ADAPTER_INFO[(len / sizeof(IP_ADAPTER_INFO)) + 1]; |
| 336 | ret = GetAdaptersInfo(adapter_info, &len); |
| 337 | |
| 338 | if (SUCCEEDED(ret)) Memory::WriteBigEData(adapter_info->Address, CommandBuffer.PayloadBuffer.at(1).m_Address, 4); |
| 339 | else Memory::WriteBigEData(default_address, CommandBuffer.PayloadBuffer.at(1).m_Address, 4); |
| 340 | delete[] adapter_info; |
| 341 | #else |
| 342 | Memory::WriteBigEData(default_address, CommandBuffer.PayloadBuffer.at(1).m_Address, 4); |
| 343 | #endif |
| 344 | break; |
| 345 | } |
| 346 | |
| 347 | default: |
| 348 | INFO_LOG(WII_IPC_NET, "NET_NCD_MANAGE IOCtlV: %#x", CommandBuffer.Parameter)do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 348, "NET_NCD_MANAGE IOCtlV: %#x", CommandBuffer.Parameter) ; } } while (0); |
| 349 | break; |
| 350 | } |
| 351 | |
| 352 | Memory::Write_U32(ReturnValue, _CommandAddress+4); |
| 353 | return true; |
| 354 | } |
| 355 | |
| 356 | // ********************************************************************************** |
| 357 | // Handle /dev/net/ip/top requests |
| 358 | CWII_IPC_HLE_Device_net_ip_top::CWII_IPC_HLE_Device_net_ip_top(u32 _DeviceID, const std::string& _rDeviceName) |
| 359 | : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) |
| 360 | { |
| 361 | } |
| 362 | |
| 363 | CWII_IPC_HLE_Device_net_ip_top::~CWII_IPC_HLE_Device_net_ip_top() |
| 364 | { |
| 365 | } |
| 366 | |
| 367 | bool CWII_IPC_HLE_Device_net_ip_top::Open(u32 _CommandAddress, u32 _Mode) |
| 368 | { |
| 369 | INFO_LOG(WII_IPC_NET, "NET_IP_TOP: Open")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 369, "NET_IP_TOP: Open"); } } while (0); |
| 370 | Memory::Write_U32(GetDeviceID(), _CommandAddress+4); |
| 371 | m_Active = true; |
| 372 | return true; |
| 373 | } |
| 374 | |
| 375 | bool CWII_IPC_HLE_Device_net_ip_top::Close(u32 _CommandAddress, bool _bForce) |
| 376 | { |
| 377 | INFO_LOG(WII_IPC_NET, "NET_IP_TOP: Close")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 377, "NET_IP_TOP: Close"); } } while (0); |
| 378 | if (!_bForce) |
| 379 | Memory::Write_U32(0, _CommandAddress + 4); |
| 380 | m_Active = false; |
| 381 | return true; |
| 382 | } |
| 383 | |
| 384 | bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 _CommandAddress) |
| 385 | { |
| 386 | u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10); |
| 387 | u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14); |
| 388 | u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); |
| 389 | u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C); |
| 390 | u32 Command = Memory::Read_U32(_CommandAddress + 0x0C); |
| 391 | |
| 392 | // 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); |
| 393 | |
| 394 | u32 ReturnValue = ExecuteCommand(Command, BufferIn, BufferInSize, BufferOut, BufferOutSize); |
| 395 | Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); |
| 396 | |
| 397 | return true; |
| 398 | } |
| 399 | struct bind_params |
| 400 | { |
| 401 | u32 socket; |
| 402 | u32 has_name; |
| 403 | u8 name[28]; |
| 404 | }; |
| 405 | |
| 406 | struct GC_sockaddr |
| 407 | { |
| 408 | u8 sa_len; |
| 409 | u8 sa_family; |
| 410 | s8 sa_data[14]; |
| 411 | }; |
| 412 | |
| 413 | struct GC_in_addr |
| 414 | { |
| 415 | u32 s_addr_; // this cannot be named s_addr under windows - collides with some crazy define. |
| 416 | }; |
| 417 | |
| 418 | struct GC_sockaddr_in |
| 419 | { |
| 420 | u8 sin_len; |
| 421 | u8 sin_family; |
| 422 | u16 sin_port; |
| 423 | struct GC_in_addr sin_addr; |
| 424 | s8 sin_zero[8]; |
| 425 | }; |
| 426 | |
| 427 | u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command, u32 _BufferIn, u32 BufferInSize, u32 BufferOut, u32 BufferOutSize) |
| 428 | { |
| 429 | // Clean the location of the output buffer to zeros as a safety precaution */ |
| 430 | Memory::Memset(BufferOut, 0, BufferOutSize); |
| 431 | |
| 432 | switch (_Command) |
| 433 | { |
| 434 | case IOCTL_SO_STARTUP: |
| 435 | break; |
| 436 | |
| 437 | case IOCTL_SO_SOCKET: |
| 438 | { |
| 439 | u32 AF = Memory::Read_U32(_BufferIn); |
| 440 | u32 TYPE = Memory::Read_U32(_BufferIn + 0x04); |
| 441 | u32 PROT = Memory::Read_U32(_BufferIn + 0x04 * 2); |
| 442 | // u32 Unk1 = Memory::Read_U32(_BufferIn + 0x04 * 3); |
| 443 | u32 Socket = (u32)socket(AF, TYPE, PROT); |
| 444 | return Common::swap32(Socket); // So it doesn't get mangled later on |
| 445 | break; |
| 446 | } |
| 447 | |
| 448 | case IOCTL_SO_BIND: |
| 449 | { |
| 450 | bind_params *addr = (bind_params*)Memory::GetPointer(_BufferIn); |
| 451 | GC_sockaddr_in addrPC; |
| 452 | memcpy(&addrPC, addr->name, sizeof(GC_sockaddr_in)); |
| 453 | sockaddr_in address; |
| 454 | address.sin_family = addrPC.sin_family; |
| 455 | address.sin_addr.s_addr = addrPC.sin_addr.s_addr_; |
| 456 | address.sin_port = htons(addrPC.sin_port); |
| 457 | int Return = bind(addr->socket, (sockaddr*)&address, sizeof(address)); |
| 458 | return Return; |
| 459 | //int bind(int s, struct sockaddr *addr, int addrlen); |
| 460 | break; |
| 461 | } |
| 462 | |
| 463 | case IOCTL_SO_LISTEN: |
| 464 | { |
| 465 | u32 S = Memory::Read_U32(_BufferIn); |
| 466 | u32 BACKLOG = Memory::Read_U32(_BufferIn + 0x04); |
| 467 | u32 Return = listen(S, BACKLOG); |
| 468 | return Return; |
| 469 | break; |
| 470 | } |
| 471 | |
| 472 | case IOCTL_SO_ACCEPT: |
| 473 | { |
| 474 | //TODO: (Sonic)Check if this is correct |
| 475 | u32 S = Memory::Read_U32(_BufferIn); |
| 476 | socklen_t addrlen; |
| 477 | struct sockaddr_in address; |
| 478 | u32 Return = (u32)accept(S, (struct sockaddr *)&address, &addrlen); |
| 479 | GC_sockaddr_in *addr = (GC_sockaddr_in*)Memory::GetPointer(BufferOut); |
| 480 | addr->sin_family = (u8)address.sin_family; |
| 481 | addr->sin_addr.s_addr_ = address.sin_addr.s_addr; |
| 482 | addr->sin_port = address.sin_port; |
| 483 | socklen_t *Len = (socklen_t *)Memory::GetPointer(BufferOut + 0x04); |
| 484 | *Len = addrlen; |
| 485 | return Return; |
| 486 | //int accept(int s, struct sockaddr *addr, int *addrlen); |
| 487 | ///dev/net/ip/top::IOCtl request 0x1 (BufferIn: (000318c0, 4), BufferOut: (00058a4c, 8) |
| 488 | } |
| 489 | |
| 490 | case IOCTL_SO_GETHOSTID: |
| 491 | return 127 << 24 | 1; |
| 492 | break; |
| 493 | |
| 494 | default: |
| 495 | INFO_LOG(WII_IPC_NET,"/dev/net/ip/top::IOCtl request 0x%x (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 496, "/dev/net/ip/top::IOCtl request 0x%x (BufferIn: (%08x, %i), BufferOut: (%08x, %i)" , _Command, _BufferIn, BufferInSize, BufferOut, BufferOutSize ); } } while (0) |
| 496 | _Command, _BufferIn, BufferInSize, BufferOut, BufferOutSize)do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 496, "/dev/net/ip/top::IOCtl request 0x%x (BufferIn: (%08x, %i), BufferOut: (%08x, %i)" , _Command, _BufferIn, BufferInSize, BufferOut, BufferOutSize ); } } while (0); |
| 497 | break; |
| 498 | } |
| 499 | |
| 500 | // We return a success for any potential unknown requests |
| 501 | return 0; |
| 502 | } |
| 503 | |
| 504 | bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 _CommandAddress) |
| 505 | { |
| 506 | u32 ReturnValue = 0; |
| 507 | |
| 508 | SIOCtlVBuffer CommandBuffer(_CommandAddress); |
| 509 | switch (CommandBuffer.Parameter) |
| 510 | { |
| 511 | case IOCTL_SO_BIND: |
| 512 | case IOCTLV_SO_RECVFROM: |
| 513 | case IOCTL_SO_SOCKET: |
| 514 | case IOCTL_SO_GETHOSTID: |
| 515 | case IOCTL_SO_STARTUP: |
| 516 | //break; |
| 517 | |
| 518 | default: |
| 519 | INFO_LOG(WII_IPC_NET, "NET_IP_TOP IOCtlV: 0x%08X\n", CommandBuffer.Parameter)do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO , LogTypes::WII_IPC_NET, "/home/anal/dolphin-emu/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp" , 519, "NET_IP_TOP IOCtlV: 0x%08X\n", CommandBuffer.Parameter ); } } while (0); |
| 520 | break; |
| 521 | } |
| 522 | |
| 523 | Memory::Write_U32(ReturnValue, _CommandAddress+4); |
| 524 | return true; |
| 525 | } |