diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj
index df209f43ce..dece999185 100644
--- a/Source/Core/Core/Core.vcxproj
+++ b/Source/Core/Core/Core.vcxproj
@@ -320,6 +320,7 @@
+
@@ -520,6 +521,7 @@
+
diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters
index 017c32f865..c05fba9a38 100644
--- a/Source/Core/Core/Core.vcxproj.filters
+++ b/Source/Core/Core/Core.vcxproj.filters
@@ -559,6 +559,9 @@
HW %28Flipper/Hollywood%29\GCMemcard
+
+ IPC HLE %28IOS/Starlet%29\Net
+
@@ -1042,6 +1045,9 @@
IPC HLE %28IOS/Starlet%29\Net
+
+ IPC HLE %28IOS/Starlet%29\Net
+
diff --git a/Source/Core/Core/Src/IPC_HLE/ICMP.h b/Source/Core/Core/Src/IPC_HLE/ICMP.h
new file mode 100644
index 0000000000..abb99b9ded
--- /dev/null
+++ b/Source/Core/Core/Src/IPC_HLE/ICMP.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#ifdef _WIN32
+#include
+#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);
diff --git a/Source/Core/Core/Src/IPC_HLE/ICMPWin.cpp b/Source/Core/Core/Src/IPC_HLE/ICMPWin.cpp
new file mode 100644
index 0000000000..8c90ce3ea3
--- /dev/null
+++ b/Source/Core/Core/Src/IPC_HLE/ICMPWin.cpp
@@ -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;
+}
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 8dc5fd4c19..c5361df01b 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
@@ -50,6 +50,7 @@ it failed)
#include "FileUtil.h"
#include
#include
+#include "ICMP.h"
#ifdef _WIN32
#include
@@ -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;
}
+ 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;
+ }
+
default:
WARN_LOG(WII_IPC_NET,"0x%x (BufferIn: (%08x, %i), BufferIn2: (%08x, %i)",
- _Parameter, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2);
+ 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;
}
+
return 0;
}
-bool CWII_IPC_HLE_Device_net_ip_top::IOCtlV(u32 _CommandAddress)
+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);
- break;
- }
-
- Memory::Write_U32(ReturnValue, _CommandAddress+4);
+ u32 return_value = ExecuteCommandV(SIOCtlVBuffer(CommandAddress));
+ Memory::Write_U32(return_value, CommandAddress + 4);
return true;
}
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 da5545a069..11e100c837 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
@@ -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);
};
// **********************************************************************************