From 570a12dcd11710ffe00661f765fbb85ac03a457d Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Fri, 17 Feb 2012 00:41:31 -0800 Subject: [PATCH] Fix ICMP ping. Obey timeout. --- Source/Core/Core/Src/IPC_HLE/ICMP.h | 4 +- Source/Core/Core/Src/IPC_HLE/ICMPWin.cpp | 41 ++++++++--- .../Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp | 70 ++++++++++++------- 3 files changed, 78 insertions(+), 37 deletions(-) diff --git a/Source/Core/Core/Src/IPC_HLE/ICMP.h b/Source/Core/Core/Src/IPC_HLE/ICMP.h index abb99b9ded..c04e74ae0c 100644 --- a/Source/Core/Core/Src/IPC_HLE/ICMP.h +++ b/Source/Core/Core/Src/IPC_HLE/ICMP.h @@ -6,5 +6,5 @@ #include "Common.h" -int icmp_echo_req(u32 s, sockaddr_in *addr, u8 *data, u32 data_length); -int icmp_echo_rep(u32 s, sockaddr_in *addr, const u8 *data, u32 data_length); +int icmp_echo_req(const u32 s, const sockaddr_in *addr, const u8 *data, const u32 data_length); +int icmp_echo_rep(const u32 s, sockaddr_in *addr, const u32 timeout, const u32 data_length); diff --git a/Source/Core/Core/Src/IPC_HLE/ICMPWin.cpp b/Source/Core/Core/Src/IPC_HLE/ICMPWin.cpp index 8c90ce3ea3..a5d0cd240e 100644 --- a/Source/Core/Core/Src/IPC_HLE/ICMPWin.cpp +++ b/Source/Core/Core/Src/IPC_HLE/ICMPWin.cpp @@ -8,7 +8,6 @@ enum enum { - // id/seq/data come from wii ICMP_HDR_LEN = 4, IP_HDR_LEN = 20 }; @@ -35,8 +34,8 @@ static u8 workspace[56]; * NOTE: to handle odd number of bytes, last (even) byte in * buffer have a value of 0 (we assume that it does) */ -u16 cksum(u16 *buffer, int length) -{ +u16 cksum(const u16 *buffer, int length) +{ u32 sum = 0; while (length > 0) @@ -51,7 +50,7 @@ u16 cksum(u16 *buffer, int length) return (u16)~sum; } -int icmp_echo_req(u32 s, sockaddr_in *addr, u8 *data, u32 data_length) +int icmp_echo_req(const u32 s, const sockaddr_in *addr, const u8 *data, const u32 data_length) { memset(workspace, 0, sizeof(workspace)); icmp_hdr *header = (icmp_hdr *)workspace; @@ -62,18 +61,38 @@ int icmp_echo_req(u32 s, sockaddr_in *addr, u8 *data, u32 data_length) header->checksum = cksum((u16 *)header, ICMP_HDR_LEN + data_length); - return sendto((SOCKET)s, (LPSTR)header, ICMP_HDR_LEN + data_length, 0, + int num_bytes = sendto((SOCKET)s, (LPSTR)header, ICMP_HDR_LEN + data_length, 0, (sockaddr *)addr, sizeof(sockaddr)); + + if (num_bytes >= ICMP_HDR_LEN) + num_bytes -= ICMP_HDR_LEN; + + return num_bytes; } -int icmp_echo_rep(u32 s, sockaddr_in *addr, const u8 *data, u32 data_length) +int icmp_echo_rep(const u32 s, sockaddr_in *addr, const u32 timeout, const u32 data_length) { memset(workspace, 0, sizeof(workspace)); int addr_length = sizeof(sockaddr_in); - int ret = recvfrom((SOCKET)s, (LPSTR)workspace, - IP_HDR_LEN + ICMP_HDR_LEN + data_length, - 0, (sockaddr *)addr, &addr_length); + int num_bytes = 0; - // TODO do we need to memcmp the data? - return ret; + fd_set read_fds; + FD_ZERO(&read_fds); + FD_SET(s, &read_fds); + + timeval t; + t.tv_sec = timeout / 1000; + if (select(0, &read_fds, NULL, NULL, &t) > 0) + { + num_bytes = recvfrom((SOCKET)s, (LPSTR)workspace, + IP_HDR_LEN + ICMP_HDR_LEN + data_length, + 0, (sockaddr *)addr, &addr_length); + + // TODO do we need to memcmp the data? + + if (num_bytes >= IP_HDR_LEN + ICMP_HDR_LEN) + num_bytes -= IP_HDR_LEN + ICMP_HDR_LEN; + } + + return num_bytes; } 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 202ebc8191..1d2af7946a 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 @@ -154,6 +154,12 @@ bool CWII_IPC_HLE_Device_net_kd_request::IOCtl(u32 _CommandAddress) WARN_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_UNLOCK_SOCKET - NI"); break; + case IOCTL_NWC24_REQUEST_REGISTER_USER_ID: + WARN_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_REQUEST_REGISTER_USER_ID"); + Memory::Write_U32(0, BufferOut); + Memory::Write_U32(0, BufferOut+4); + break; + case IOCTL_NWC24_REQUEST_GENERATED_USER_ID: // (Input: none, Output: 32 bytes) WARN_LOG(WII_IPC_NET, "NET_KD_REQ: IOCTL_NWC24_REQUEST_GENERATED_USER_ID"); //Memory::Write_U32(0xFFFFFFDC, BufferOut); @@ -817,34 +823,35 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command, "Socket: %08X, BufferIn: (%08x, %i), BufferOut: (%08x, %i)", sock, _BufferIn, BufferInSize, _BufferOut, BufferOutSize); - struct sockaddr sa; + sockaddr sa; socklen_t sa_len; - sa_len = sizeof(sa); + sa_len = sizeof(sa); int ret = getsockname(sock, &sa, &sa_len); Memory::Write_U8(BufferOutSize, _BufferOut); - Memory::Write_U8(sa.sa_family & 0xFF, _BufferOut+1); - Memory::WriteBigEData((u8*)&sa.sa_data, _BufferOut+2, BufferOutSize-2); + Memory::Write_U8(sa.sa_family & 0xFF, _BufferOut + 1); + Memory::WriteBigEData((u8*)&sa.sa_data, _BufferOut + 2, BufferOutSize - 2); return ret; } case IOCTL_SO_GETPEERNAME: { u32 sock = Memory::Read_U32(_BufferIn); - WARN_LOG(WII_IPC_NET, "IOCTL_SO_GETPEERNAME " - "Socket: %08X, BufferIn: (%08x, %i), BufferOut: (%08x, %i)", - sock, _BufferIn, BufferInSize, _BufferOut, BufferOutSize); - - struct sockaddr sa; + sockaddr sa; socklen_t sa_len; - sa_len = sizeof(sa); + sa_len = sizeof(sa); + int ret = getpeername(sock, &sa, &sa_len); Memory::Write_U8(BufferOutSize, _BufferOut); - Memory::Write_U8(sa.sa_family & 0xFF, _BufferOut+1); - Memory::WriteBigEData((u8*)&sa.sa_data, _BufferOut+2, BufferOutSize-2); + Memory::Write_U8(AF_INET, _BufferOut + 1); + Memory::WriteBigEData((u8*)&sa.sa_data, _BufferOut + 2, BufferOutSize - 2); + + WARN_LOG(WII_IPC_NET, "IOCTL_SO_GETPEERNAME(%x)", sock); + return ret; } + case IOCTL_SO_GETHOSTID: { WARN_LOG(WII_IPC_NET, "IOCTL_SO_GETHOSTID " @@ -993,7 +1000,7 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command, // AF type? u32 arg = Memory::Read_U32(_BufferIn); u32 sock = (u32)socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); - ERROR_LOG(WII_IPC_NET, "IOCTL_SO_ICMPSOCKET(%x) %x", arg, sock); + DEBUG_LOG(WII_IPC_NET, "IOCTL_SO_ICMPSOCKET(%x) %x", arg, sock); return getNetErrorCode(sock, "IOCTL_SO_ICMPSOCKET", false); } @@ -1005,7 +1012,7 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command, { u32 sock = Memory::Read_U32(_BufferIn); u32 ret = closesocket(sock); - ERROR_LOG(WII_IPC_NET, "IOCTL_SO_ICMPCLOSE(%x) %x", sock, ret); + DEBUG_LOG(WII_IPC_NET, "IOCTL_SO_ICMPCLOSE(%x) %x", sock, ret); return getNetErrorCode(ret, "IOCTL_SO_ICMPCLOSE", false); } @@ -1396,7 +1403,7 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer { u8 length; u8 addr_family; - u16 port; + u16 icmp_id; u32 ip; } ip_info; @@ -1411,14 +1418,14 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer ip_info.length = Memory::Read_U8(_BufferIn + 16); ip_info.addr_family = Memory::Read_U8(_BufferIn + 17); - ip_info.port = Memory::Read_U16(_BufferIn + 18); + ip_info.icmp_id = Memory::Read_U16(_BufferIn + 18); ip_info.ip = Memory::Read_U32(_BufferIn + 20); - if (ip_info.length != 8 || ip_info.addr_family != AF_INET || ip_info.port != 0) + if (ip_info.length != 8 || ip_info.addr_family != AF_INET) { WARN_LOG(WII_IPC_NET, "IOCTLV_SO_ICMPPING strange IPInfo:\n" - "length %x addr_family %x port %x", - ip_info.length, ip_info.addr_family, ip_info.port); + "length %x addr_family %x", + ip_info.length, ip_info.addr_family); } DEBUG_LOG(WII_IPC_NET, "IOCTLV_SO_ICMPPING %x", ip_info.ip); @@ -1427,13 +1434,28 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer addr.sin_family = AF_INET; addr.sin_addr.S_un.S_addr = Common::swap32(ip_info.ip); memset(addr.sin_zero, 0, 8); - u8 *data = Memory::GetPointer(_BufferIn2); - - int ret = icmp_echo_req(sock, &addr, data, BufferInSize2); - if (ret >= 0) + + u8 data[0x20]; + memset(data, 0, sizeof(data)); + u32 icmp_length = sizeof(data); + + if (BufferInSize2 == sizeof(data)) + memcpy(data, Memory::GetPointer(_BufferIn2), BufferInSize2); + else { - //icmp_echo_rep(sock, &addr, data, BufferInSize2); + // TODO sequence number is incremented either statically, by + // port, or by socket. Doesn't seem to matter, so we just leave + // it 0 + ((u16 *)data)[0] = Common::swap16(ip_info.icmp_id); + icmp_length = 22; } + + int ret = icmp_echo_req(sock, &addr, data, icmp_length); + if (ret == icmp_length) + { + ret = icmp_echo_rep(sock, &addr, timeout, icmp_length); + } + // TODO proper error codes return 0; }