implement ICMP stuff (on windows). should be very similar on *nix...might just be able to compile the current code :)

This commit is contained in:
Shawn Hoffman 2012-02-12 23:19:22 -08:00
parent 2046fb0457
commit 4e62015e9a
6 changed files with 199 additions and 21 deletions

View File

@ -320,6 +320,7 @@
<ClCompile Include="Src\HW\WiimoteReal\WiimoteReal.cpp" />
<ClCompile Include="Src\HW\WII_IOB.cpp" />
<ClCompile Include="Src\HW\WII_IPC.cpp" />
<ClCompile Include="Src\IPC_HLE\ICMPWin.cpp" />
<ClCompile Include="Src\IPC_HLE\WiiMote_HID_Attr.cpp" />
<ClCompile Include="Src\IPC_HLE\WII_IPC_HLE.cpp" />
<ClCompile Include="Src\IPC_HLE\WII_IPC_HLE_Device_DI.cpp" />
@ -520,6 +521,7 @@
<ClInclude Include="Src\HW\WII_IPC.h" />
<ClInclude Include="Src\IPC_HLE\hci.h" />
<ClInclude Include="Src\IPC_HLE\fakepoll.h" />
<ClInclude Include="Src\IPC_HLE\ICMP.h" />
<ClInclude Include="Src\IPC_HLE\l2cap.h" />
<ClInclude Include="Src\IPC_HLE\WiiMote_HID_Attr.h" />
<ClInclude Include="Src\IPC_HLE\WII_IPC_HLE.h" />

View File

@ -559,6 +559,9 @@
<ClCompile Include="Src\HW\GCMemcard.cpp">
<Filter>HW %28Flipper/Hollywood%29\GCMemcard</Filter>
</ClCompile>
<ClCompile Include="Src\IPC_HLE\ICMPWin.cpp">
<Filter>IPC HLE %28IOS/Starlet%29\Net</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Src\ConfigManager.h" />
@ -1042,6 +1045,9 @@
<ClInclude Include="Src\IPC_HLE\fakepoll.h">
<Filter>IPC HLE %28IOS/Starlet%29\Net</Filter>
</ClInclude>
<ClInclude Include="Src\IPC_HLE\ICMP.h">
<Filter>IPC HLE %28IOS/Starlet%29\Net</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />

View File

@ -0,0 +1,10 @@
#pragma once
#ifdef _WIN32
#include <winsock2.h>
#endif
#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);

View File

@ -0,0 +1,79 @@
#include "ICMP.h"
enum
{
ICMP_ECHOREPLY = 0,
ICMP_ECHOREQ = 8
};
enum
{
// id/seq/data come from wii
ICMP_HDR_LEN = 4,
IP_HDR_LEN = 20
};
#pragma pack(push, 1)
struct icmp_hdr
{
u8 type;
u8 code;
u16 checksum;
u16 id;
u16 seq;
char data[1];
};
#pragma pack(pop)
static u8 workspace[56];
/*
* Description:
* Calculate Internet checksum for data buffer and length (one's
* complement sum of 16-bit words). Used in IP, ICMP, UDP, IGMP.
*
* 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)
{
u32 sum = 0;
while (length > 0)
{
sum += *(buffer++);
length -= 2;
}
sum = (sum & 0xffff) + (sum >> 16);
sum += sum >> 16;
return (u16)~sum;
}
int icmp_echo_req(u32 s, sockaddr_in *addr, u8 *data, u32 data_length)
{
memset(workspace, 0, sizeof(workspace));
icmp_hdr *header = (icmp_hdr *)workspace;
header->type = ICMP_ECHOREQ;
header->code = 0;
header->checksum = 0;
memcpy(&header->id, data, data_length);
header->checksum = cksum((u16 *)header, ICMP_HDR_LEN + data_length);
return sendto((SOCKET)s, (LPSTR)header, ICMP_HDR_LEN + data_length, 0,
(sockaddr *)addr, sizeof(sockaddr));
}
int icmp_echo_rep(u32 s, sockaddr_in *addr, const u8 *data, 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);
// TODO do we need to memcmp the data?
return ret;
}

View File

@ -50,6 +50,7 @@ it failed)
#include "FileUtil.h"
#include <stdio.h>
#include <string>
#include "ICMP.h"
#ifdef _WIN32
#include <ws2tcpip.h>
@ -969,10 +970,39 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command,
break;
}
case IOCTL_SO_ICMPSOCKET:
{
// 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);
return getNetErrorCode(sock, "IOCTL_SO_ICMPSOCKET", false);
}
case IOCTL_SO_ICMPCANCEL:
ERROR_LOG(WII_IPC_NET, "IOCTL_SO_ICMPCANCEL");
goto default_;
case IOCTL_SO_ICMPCLOSE:
{
u32 sock = Memory::Read_U32(_BufferIn);
u32 ret = closesocket(sock);
ERROR_LOG(WII_IPC_NET, "IOCTL_SO_ICMPCLOSE(%x) %x", sock, ret);
return getNetErrorCode(ret, "IOCTL_SO_ICMPCLOSE", false);
}
default:
WARN_LOG(WII_IPC_NET,"0x%x "
"BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
_Command, _BufferIn, BufferInSize, _BufferOut, BufferOutSize);
default_:
if (BufferInSize)
{
ERROR_LOG(WII_IPC_NET, "in addr %x size %x", _BufferIn, BufferInSize);
ERROR_LOG(WII_IPC_NET, "\n%s",
ArrayToString(Memory::GetPointer(_BufferIn), BufferInSize, 4).c_str()
);
}
break;
}
@ -980,7 +1010,7 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommand(u32 _Command,
return 0;
}
u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer CommandBuffer)
u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(SIOCtlVBuffer& CommandBuffer)
{
u32 _BufferIn = 0, _BufferIn2 = 0, _BufferIn3 = 0;
u32 BufferInSize = 0, BufferInSize2 = 0, BufferInSize3 = 0;
@ -1036,7 +1066,7 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffe
u32 param = 0, param2 = 0, param3, param4, param5 = 0;
switch (_Parameter)
switch (CommandBuffer.Parameter)
{
case IOCTLV_SO_GETINTERFACEOPT:
{
@ -1342,32 +1372,83 @@ u32 CWII_IPC_HLE_Device_net_ip_top::ExecuteCommandV(u32 _Parameter, SIOCtlVBuffe
return ret;
}
default:
WARN_LOG(WII_IPC_NET,"0x%x (BufferIn: (%08x, %i), BufferIn2: (%08x, %i)",
_Parameter, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2);
break;
case IOCTLV_SO_ICMPPING:
{
struct
{
u8 length;
u8 addr_family;
u16 port;
u32 ip;
} ip_info;
u32 sock = Memory::Read_U32(_BufferIn);
u32 num_ip = Memory::Read_U32(_BufferIn + 4);
u64 timeout = Memory::Read_U64(_BufferIn + 8);
if (num_ip != 1)
{
WARN_LOG(WII_IPC_NET, "IOCTLV_SO_ICMPPING %i IPs", num_ip);
}
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.ip = Memory::Read_U32(_BufferIn + 20);
if (ip_info.length != 8 || ip_info.addr_family != AF_INET || ip_info.port != 0)
{
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);
}
DEBUG_LOG(WII_IPC_NET, "IOCTLV_SO_ICMPPING %x", ip_info.ip);
sockaddr_in addr;
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)
{
icmp_echo_rep(sock, &addr, data, BufferInSize2);
}
// TODO proper error codes
return 0;
}
bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 _CommandAddress)
{
u32 ReturnValue = 0;
SIOCtlVBuffer CommandBuffer(_CommandAddress);
switch (CommandBuffer.Parameter)
{
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);
WARN_LOG(WII_IPC_NET,"0x%x (BufferIn: (%08x, %i), BufferIn2: (%08x, %i)",
CommandBuffer.Parameter, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2);
default_:
for (int i = 0; i < CommandBuffer.NumberInBuffer; ++i)
{
ERROR_LOG(WII_IPC_NET, "in %i addr %x size %x", i,
CommandBuffer.InBuffer.at(i).m_Address, CommandBuffer.InBuffer.at(i).m_Size);
ERROR_LOG(WII_IPC_NET, "\n%s",
ArrayToString(
Memory::GetPointer(CommandBuffer.InBuffer.at(i).m_Address),
CommandBuffer.InBuffer.at(i).m_Size, 4).c_str()
);
}
for (int i = 0; i < CommandBuffer.NumberPayloadBuffer; ++i)
{
ERROR_LOG(WII_IPC_NET, "out %i addr %x size %x", i,
CommandBuffer.PayloadBuffer.at(i).m_Address, CommandBuffer.PayloadBuffer.at(i).m_Size, 4);
}
break;
}
Memory::Write_U32(ReturnValue, _CommandAddress+4);
return 0;
}
bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 CommandAddress)
{
u32 return_value = ExecuteCommandV(SIOCtlVBuffer(CommandAddress));
Memory::Write_U32(return_value, CommandAddress + 4);
return true;
}

View File

@ -409,7 +409,7 @@ private:
};
u32 ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _BufferInSize, u32 _BufferOut, u32 _BufferOutSize);
u32 ExecuteCommandV(u32 _Parameter, SIOCtlVBuffer CommandBuffer);
u32 ExecuteCommandV(SIOCtlVBuffer& CommandBuffer);
};
// **********************************************************************************