Merge pull request #5043 from lioncash/net

IOS/Network/IP/Top: Separate behaviors into their own functions
This commit is contained in:
Matthew Parlane 2017-03-12 16:12:43 +13:00 committed by GitHub
commit d042121ebd
2 changed files with 815 additions and 748 deletions

View File

@ -155,81 +155,157 @@ IPCCommandResult NetIPTop::IOCtl(const IOCtlRequest& request)
return GetDefaultReply(IPC_EACCES); return GetDefaultReply(IPC_EACCES);
} }
s32 return_value = 0;
switch (request.request) switch (request.request)
{ {
case IOCTL_SO_STARTUP: case IOCTL_SO_STARTUP:
{ return StartUp(request);
request.Log(GetDeviceName(), LogTypes::IOS_WC24); case IOCTL_SO_SOCKET:
return Socket(request);
case IOCTL_SO_ICMPSOCKET:
return ICMPSocket(request);
case IOCTL_SO_CLOSE:
case IOCTL_SO_ICMPCLOSE:
return Close(request);
case IOCTL_SO_ACCEPT:
case IOCTL_SO_BIND:
case IOCTL_SO_CONNECT:
case IOCTL_SO_FCNTL:
return DoSock(request);
case IOCTL_SO_SHUTDOWN:
return Shutdown(request);
case IOCTL_SO_LISTEN:
return Listen(request);
case IOCTL_SO_GETSOCKOPT:
return GetSockOpt(request);
case IOCTL_SO_SETSOCKOPT:
return SetSockOpt(request);
case IOCTL_SO_GETSOCKNAME:
return GetSockName(request);
case IOCTL_SO_GETPEERNAME:
return GetPeerName(request);
case IOCTL_SO_GETHOSTID:
return GetHostID(request);
case IOCTL_SO_INETATON:
return InetAToN(request);
case IOCTL_SO_INETPTON:
return InetPToN(request);
case IOCTL_SO_INETNTOP:
return InetNToP(request);
case IOCTL_SO_POLL:
return Poll(request);
case IOCTL_SO_GETHOSTBYNAME:
return GetHostByName(request);
case IOCTL_SO_ICMPCANCEL:
return ICMPCancel(request);
default:
request.DumpUnknown(GetDeviceName(), LogTypes::IOS_NET);
break; break;
} }
case IOCTL_SO_SOCKET:
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult NetIPTop::IOCtlV(const IOCtlVRequest& request)
{
switch (request.request)
{
case IOCTLV_SO_GETINTERFACEOPT:
return GetInterfaceOpt(request);
case IOCTLV_SO_SENDTO:
return SendTo(request);
case IOCTLV_SO_RECVFROM:
return RecvFrom(request);
case IOCTLV_SO_GETADDRINFO:
return GetAddressInfo(request);
case IOCTLV_SO_ICMPPING:
return ICMPPing(request);
default:
request.DumpUnknown(GetDeviceName(), LogTypes::IOS_NET);
break;
}
return GetDefaultReply(IPC_SUCCESS);
}
void NetIPTop::Update()
{
WiiSockMan::GetInstance().Update();
}
IPCCommandResult NetIPTop::StartUp(const IOCtlRequest& request)
{
request.Log(GetDeviceName(), LogTypes::IOS_WC24);
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult NetIPTop::Socket(const IOCtlRequest& request)
{ {
u32 af = Memory::Read_U32(request.buffer_in); u32 af = Memory::Read_U32(request.buffer_in);
u32 type = Memory::Read_U32(request.buffer_in + 4); u32 type = Memory::Read_U32(request.buffer_in + 4);
u32 prot = Memory::Read_U32(request.buffer_in + 8); u32 prot = Memory::Read_U32(request.buffer_in + 8);
WiiSockMan& sm = WiiSockMan::GetInstance(); WiiSockMan& sm = WiiSockMan::GetInstance();
return_value = sm.NewSocket(af, type, prot); const s32 return_value = sm.NewSocket(af, type, prot);
INFO_LOG(IOS_NET, "IOCTL_SO_SOCKET " INFO_LOG(IOS_NET, "IOCTL_SO_SOCKET "
"Socket: %08x (%d,%d,%d), BufferIn: (%08x, %i), BufferOut: (%08x, %i)", "Socket: %08x (%d,%d,%d), BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
return_value, af, type, prot, request.buffer_in, request.buffer_in_size, return_value, af, type, prot, request.buffer_in, request.buffer_in_size,
request.buffer_out, request.buffer_out_size); request.buffer_out, request.buffer_out_size);
break;
return GetDefaultReply(return_value);
} }
case IOCTL_SO_ICMPSOCKET:
IPCCommandResult NetIPTop::ICMPSocket(const IOCtlRequest& request)
{ {
u32 pf = Memory::Read_U32(request.buffer_in); u32 pf = Memory::Read_U32(request.buffer_in);
WiiSockMan& sm = WiiSockMan::GetInstance(); WiiSockMan& sm = WiiSockMan::GetInstance();
return_value = sm.NewSocket(pf, SOCK_RAW, IPPROTO_ICMP); const s32 return_value = sm.NewSocket(pf, SOCK_RAW, IPPROTO_ICMP);
INFO_LOG(IOS_NET, "IOCTL_SO_ICMPSOCKET(%x) %d", pf, return_value); INFO_LOG(IOS_NET, "IOCTL_SO_ICMPSOCKET(%x) %d", pf, return_value);
break; return GetDefaultReply(return_value);
} }
case IOCTL_SO_CLOSE:
case IOCTL_SO_ICMPCLOSE: IPCCommandResult NetIPTop::Close(const IOCtlRequest& request)
{ {
u32 fd = Memory::Read_U32(request.buffer_in); u32 fd = Memory::Read_U32(request.buffer_in);
WiiSockMan& sm = WiiSockMan::GetInstance(); WiiSockMan& sm = WiiSockMan::GetInstance();
return_value = sm.DeleteSocket(fd); const s32 return_value = sm.DeleteSocket(fd);
INFO_LOG(IOS_NET, "%s(%x) %x", INFO_LOG(IOS_NET, "%s(%x) %x",
request.request == IOCTL_SO_ICMPCLOSE ? "IOCTL_SO_ICMPCLOSE" : "IOCTL_SO_CLOSE", fd, request.request == IOCTL_SO_ICMPCLOSE ? "IOCTL_SO_ICMPCLOSE" : "IOCTL_SO_CLOSE", fd,
return_value); return_value);
break;
return GetDefaultReply(return_value);
} }
case IOCTL_SO_ACCEPT:
case IOCTL_SO_BIND: IPCCommandResult NetIPTop::DoSock(const IOCtlRequest& request)
case IOCTL_SO_CONNECT:
case IOCTL_SO_FCNTL:
{ {
u32 fd = Memory::Read_U32(request.buffer_in); u32 fd = Memory::Read_U32(request.buffer_in);
WiiSockMan& sm = WiiSockMan::GetInstance(); WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(fd, request, static_cast<NET_IOCTL>(request.request)); sm.DoSock(fd, request, static_cast<NET_IOCTL>(request.request));
return GetNoReply(); return GetNoReply();
} }
/////////////////////////////////////////////////////////////
// TODO: Tidy all below // IPCCommandResult NetIPTop::Shutdown(const IOCtlRequest& request)
/////////////////////////////////////////////////////////////
case IOCTL_SO_SHUTDOWN:
{ {
request.Log(GetDeviceName(), LogTypes::IOS_WC24); request.Log(GetDeviceName(), LogTypes::IOS_WC24);
u32 fd = Memory::Read_U32(request.buffer_in); u32 fd = Memory::Read_U32(request.buffer_in);
u32 how = Memory::Read_U32(request.buffer_in + 4); u32 how = Memory::Read_U32(request.buffer_in + 4);
int ret = shutdown(fd, how); int ret = shutdown(fd, how);
return_value = WiiSockMan::GetNetErrorCode(ret, "SO_SHUTDOWN", false);
break; return GetDefaultReply(WiiSockMan::GetNetErrorCode(ret, "SO_SHUTDOWN", false));
} }
case IOCTL_SO_LISTEN:
IPCCommandResult NetIPTop::Listen(const IOCtlRequest& request)
{ {
u32 fd = Memory::Read_U32(request.buffer_in); u32 fd = Memory::Read_U32(request.buffer_in);
u32 BACKLOG = Memory::Read_U32(request.buffer_in + 0x04); u32 BACKLOG = Memory::Read_U32(request.buffer_in + 0x04);
u32 ret = listen(fd, BACKLOG); u32 ret = listen(fd, BACKLOG);
return_value = WiiSockMan::GetNetErrorCode(ret, "SO_LISTEN", false);
request.Log(GetDeviceName(), LogTypes::IOS_WC24); request.Log(GetDeviceName(), LogTypes::IOS_WC24);
break; return GetDefaultReply(WiiSockMan::GetNetErrorCode(ret, "SO_LISTEN", false));
} }
case IOCTL_SO_GETSOCKOPT:
IPCCommandResult NetIPTop::GetSockOpt(const IOCtlRequest& request)
{ {
u32 fd = Memory::Read_U32(request.buffer_out); u32 fd = Memory::Read_U32(request.buffer_out);
u32 level = Memory::Read_U32(request.buffer_out + 4); u32 level = Memory::Read_U32(request.buffer_out + 4);
@ -245,7 +321,7 @@ IPCCommandResult NetIPTop::IOCtl(const IOCtlRequest& request)
u32 optlen = 4; u32 optlen = 4;
int ret = getsockopt(fd, nat_level, nat_optname, (char*)&optval, (socklen_t*)&optlen); int ret = getsockopt(fd, nat_level, nat_optname, (char*)&optval, (socklen_t*)&optlen);
return_value = WiiSockMan::GetNetErrorCode(ret, "SO_GETSOCKOPT", false); const s32 return_value = WiiSockMan::GetNetErrorCode(ret, "SO_GETSOCKOPT", false);
Memory::Write_U32(optlen, request.buffer_out + 0xC); Memory::Write_U32(optlen, request.buffer_out + 0xC);
Memory::CopyToEmu(request.buffer_out + 0x10, optval, optlen); Memory::CopyToEmu(request.buffer_out + 0x10, optval, optlen);
@ -257,10 +333,11 @@ IPCCommandResult NetIPTop::IOCtl(const IOCtlRequest& request)
Memory::Write_U32(sizeof(s32), request.buffer_out + 0xC); Memory::Write_U32(sizeof(s32), request.buffer_out + 0xC);
Memory::Write_U32(last_error, request.buffer_out + 0x10); Memory::Write_U32(last_error, request.buffer_out + 0x10);
} }
break;
return GetDefaultReply(return_value);
} }
case IOCTL_SO_SETSOCKOPT: IPCCommandResult NetIPTop::SetSockOpt(const IOCtlRequest& request)
{ {
u32 fd = Memory::Read_U32(request.buffer_in); u32 fd = Memory::Read_U32(request.buffer_in);
u32 level = Memory::Read_U32(request.buffer_in + 4); u32 level = Memory::Read_U32(request.buffer_in + 4);
@ -275,36 +352,32 @@ IPCCommandResult NetIPTop::IOCtl(const IOCtlRequest& request)
"%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx " "%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx "
"%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx", "%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx",
fd, level, optname, optlen, request.buffer_in, request.buffer_in_size, fd, level, optname, optlen, request.buffer_in, request.buffer_in_size,
request.buffer_out, request.buffer_out_size, optval[0], optval[1], optval[2], request.buffer_out, request.buffer_out_size, optval[0], optval[1], optval[2], optval[3],
optval[3], optval[4], optval[5], optval[6], optval[7], optval[8], optval[9], optval[4], optval[5], optval[6], optval[7], optval[8], optval[9], optval[10], optval[11],
optval[10], optval[11], optval[12], optval[13], optval[14], optval[15], optval[16], optval[12], optval[13], optval[14], optval[15], optval[16], optval[17], optval[18],
optval[17], optval[18], optval[19]); optval[19]);
// TODO: bug booto about this, 0x2005 most likely timeout related, default value on Wii is , // TODO: bug booto about this, 0x2005 most likely timeout related, default value on Wii is ,
// 0x2001 is most likely tcpnodelay // 0x2001 is most likely tcpnodelay
if (level == 6 && (optname == 0x2005 || optname == 0x2001)) if (level == 6 && (optname == 0x2005 || optname == 0x2001))
{ return GetDefaultReply(0);
return_value = 0;
break;
}
// Do the level/optname translation // Do the level/optname translation
int nat_level = MapWiiSockOptLevelToNative(level); int nat_level = MapWiiSockOptLevelToNative(level);
int nat_optname = MapWiiSockOptNameToNative(optname); int nat_optname = MapWiiSockOptNameToNative(optname);
int ret = setsockopt(fd, nat_level, nat_optname, (char*)optval, optlen); int ret = setsockopt(fd, nat_level, nat_optname, (char*)optval, optlen);
return_value = WiiSockMan::GetNetErrorCode(ret, "SO_SETSOCKOPT", false); return GetDefaultReply(WiiSockMan::GetNetErrorCode(ret, "SO_SETSOCKOPT", false));
break;
} }
case IOCTL_SO_GETSOCKNAME:
IPCCommandResult NetIPTop::GetSockName(const IOCtlRequest& request)
{ {
u32 fd = Memory::Read_U32(request.buffer_in); u32 fd = Memory::Read_U32(request.buffer_in);
request.Log(GetDeviceName(), LogTypes::IOS_WC24); request.Log(GetDeviceName(), LogTypes::IOS_WC24);
sockaddr sa; sockaddr sa;
socklen_t sa_len; socklen_t sa_len = sizeof(sa);
sa_len = sizeof(sa);
int ret = getsockname(fd, &sa, &sa_len); int ret = getsockname(fd, &sa, &sa_len);
if (request.buffer_out_size < 2 + sizeof(sa.sa_data)) if (request.buffer_out_size < 2 + sizeof(sa.sa_data))
@ -315,19 +388,20 @@ IPCCommandResult NetIPTop::IOCtl(const IOCtlRequest& request)
if (request.buffer_out_size > 1) if (request.buffer_out_size > 1)
Memory::Write_U8(sa.sa_family & 0xFF, request.buffer_out + 1); Memory::Write_U8(sa.sa_family & 0xFF, request.buffer_out + 1);
if (request.buffer_out_size > 2) if (request.buffer_out_size > 2)
{
Memory::CopyToEmu(request.buffer_out + 2, &sa.sa_data, Memory::CopyToEmu(request.buffer_out + 2, &sa.sa_data,
std::min<size_t>(sizeof(sa.sa_data), request.buffer_out_size - 2)); std::min<size_t>(sizeof(sa.sa_data), request.buffer_out_size - 2));
return_value = ret;
break;
} }
case IOCTL_SO_GETPEERNAME:
return GetDefaultReply(ret);
}
IPCCommandResult NetIPTop::GetPeerName(const IOCtlRequest& request)
{ {
u32 fd = Memory::Read_U32(request.buffer_in); u32 fd = Memory::Read_U32(request.buffer_in);
sockaddr sa; sockaddr sa;
socklen_t sa_len; socklen_t sa_len = sizeof(sa);
sa_len = sizeof(sa);
int ret = getpeername(fd, &sa, &sa_len); int ret = getpeername(fd, &sa, &sa_len);
if (request.buffer_out_size < 2 + sizeof(sa.sa_data)) if (request.buffer_out_size < 2 + sizeof(sa.sa_data))
@ -338,19 +412,21 @@ IPCCommandResult NetIPTop::IOCtl(const IOCtlRequest& request)
if (request.buffer_out_size > 1) if (request.buffer_out_size > 1)
Memory::Write_U8(AF_INET, request.buffer_out + 1); Memory::Write_U8(AF_INET, request.buffer_out + 1);
if (request.buffer_out_size > 2) if (request.buffer_out_size > 2)
{
Memory::CopyToEmu(request.buffer_out + 2, &sa.sa_data, Memory::CopyToEmu(request.buffer_out + 2, &sa.sa_data,
std::min<size_t>(sizeof(sa.sa_data), request.buffer_out_size - 2)); std::min<size_t>(sizeof(sa.sa_data), request.buffer_out_size - 2));
INFO_LOG(IOS_NET, "IOCTL_SO_GETPEERNAME(%x)", fd);
return_value = ret;
break;
} }
case IOCTL_SO_GETHOSTID: INFO_LOG(IOS_NET, "IOCTL_SO_GETPEERNAME(%x)", fd);
return GetDefaultReply(ret);
}
IPCCommandResult NetIPTop::GetHostID(const IOCtlRequest& request)
{ {
request.Log(GetDeviceName(), LogTypes::IOS_WC24); request.Log(GetDeviceName(), LogTypes::IOS_WC24);
s32 return_value = 0;
#ifdef _WIN32 #ifdef _WIN32
DWORD forwardTableSize, ipTableSize, result; DWORD forwardTableSize, ipTableSize, result;
DWORD ifIndex = -1; DWORD ifIndex = -1;
@ -372,8 +448,8 @@ IPCCommandResult NetIPTop::IOCtl(const IOCtlRequest& request)
// find the interface IP used for the default route and use that // find the interface IP used for the default route and use that
result = GetIpForwardTable(forwardTable.get(), &forwardTableSize, FALSE); result = GetIpForwardTable(forwardTable.get(), &forwardTableSize, FALSE);
while (result == NO_ERROR || // can return ERROR_MORE_DATA on XP even after the first call
result == ERROR_MORE_DATA) // can return ERROR_MORE_DATA on XP even after the first call while (result == NO_ERROR || result == ERROR_MORE_DATA)
{ {
for (DWORD i = 0; i < forwardTable->dwNumEntries; ++i) for (DWORD i = 0; i < forwardTable->dwNumEntries; ++i)
{ {
@ -406,10 +482,11 @@ IPCCommandResult NetIPTop::IOCtl(const IOCtlRequest& request)
// default placeholder, in case of failure // default placeholder, in case of failure
if (return_value == 0) if (return_value == 0)
return_value = 192 << 24 | 168 << 16 | 1 << 8 | 150; return_value = 192 << 24 | 168 << 16 | 1 << 8 | 150;
break;
return GetDefaultReply(return_value);
} }
case IOCTL_SO_INETATON: IPCCommandResult NetIPTop::InetAToN(const IOCtlRequest& request)
{ {
std::string hostname = Memory::GetString(request.buffer_in); std::string hostname = Memory::GetString(request.buffer_in);
struct hostent* remoteHost = gethostbyname(hostname.c_str()); struct hostent* remoteHost = gethostbyname(hostname.c_str());
@ -421,45 +498,41 @@ IPCCommandResult NetIPTop::IOCtl(const IOCtlRequest& request)
"%s, BufferIn: (%08x, %i), BufferOut: (%08x, %i), IP Found: None", "%s, BufferIn: (%08x, %i), BufferOut: (%08x, %i), IP Found: None",
hostname.c_str(), request.buffer_in, request.buffer_in_size, request.buffer_out, hostname.c_str(), request.buffer_in, request.buffer_in_size, request.buffer_out,
request.buffer_out_size); request.buffer_out_size);
return_value = 0; return GetDefaultReply(0);
} }
else
{
Memory::Write_U32(Common::swap32(*(u32*)remoteHost->h_addr_list[0]), request.buffer_out); Memory::Write_U32(Common::swap32(*(u32*)remoteHost->h_addr_list[0]), request.buffer_out);
INFO_LOG(IOS_NET, "IOCTL_SO_INETATON = 0 " INFO_LOG(IOS_NET, "IOCTL_SO_INETATON = 0 "
"%s, BufferIn: (%08x, %i), BufferOut: (%08x, %i), IP Found: %08X", "%s, BufferIn: (%08x, %i), BufferOut: (%08x, %i), IP Found: %08X",
hostname.c_str(), request.buffer_in, request.buffer_in_size, request.buffer_out, hostname.c_str(), request.buffer_in, request.buffer_in_size, request.buffer_out,
request.buffer_out_size, Common::swap32(*(u32*)remoteHost->h_addr_list[0])); request.buffer_out_size, Common::swap32(*(u32*)remoteHost->h_addr_list[0]));
return_value = 1; return GetDefaultReply(1);
}
break;
} }
case IOCTL_SO_INETPTON: IPCCommandResult NetIPTop::InetPToN(const IOCtlRequest& request)
{ {
std::string address = Memory::GetString(request.buffer_in); std::string address = Memory::GetString(request.buffer_in);
INFO_LOG(IOS_NET, "IOCTL_SO_INETPTON " INFO_LOG(IOS_NET, "IOCTL_SO_INETPTON (Translating: %s)", address.c_str());
"(Translating: %s)", return GetDefaultReply(inet_pton(address.c_str(), Memory::GetPointer(request.buffer_out + 4)));
address.c_str());
return_value = inet_pton(address.c_str(), Memory::GetPointer(request.buffer_out + 4));
break;
} }
case IOCTL_SO_INETNTOP: IPCCommandResult NetIPTop::InetNToP(const IOCtlRequest& request)
{ {
// u32 af = Memory::Read_U32(BufferIn); // u32 af = Memory::Read_U32(BufferIn);
// u32 validAddress = Memory::Read_U32(request.buffer_in + 4); // u32 validAddress = Memory::Read_U32(request.buffer_in + 4);
// u32 src = Memory::Read_U32(request.buffer_in + 8); // u32 src = Memory::Read_U32(request.buffer_in + 8);
char ip_s[16]; char ip_s[16];
sprintf(ip_s, "%i.%i.%i.%i", Memory::Read_U8(request.buffer_in + 8), sprintf(ip_s, "%i.%i.%i.%i", Memory::Read_U8(request.buffer_in + 8),
Memory::Read_U8(request.buffer_in + 8 + 1), Memory::Read_U8(request.buffer_in + 8 + 2), Memory::Read_U8(request.buffer_in + 8 + 1), Memory::Read_U8(request.buffer_in + 8 + 2),
Memory::Read_U8(request.buffer_in + 8 + 3)); Memory::Read_U8(request.buffer_in + 8 + 3));
INFO_LOG(IOS_NET, "IOCTL_SO_INETNTOP %s", ip_s); INFO_LOG(IOS_NET, "IOCTL_SO_INETNTOP %s", ip_s);
Memory::CopyToEmu(request.buffer_out, (u8*)ip_s, strlen(ip_s)); Memory::CopyToEmu(request.buffer_out, (u8*)ip_s, strlen(ip_s));
break; return GetDefaultReply(0);
} }
case IOCTL_SO_POLL: IPCCommandResult NetIPTop::Poll(const IOCtlRequest& request)
{ {
// Map Wii/native poll events types // Map Wii/native poll events types
struct struct
@ -525,21 +598,19 @@ IPCCommandResult NetIPTop::IOCtl(const IOCtlRequest& request)
// Memory::Write_U32(events, request.buffer_out + 0xc*i + 4); //events // Memory::Write_U32(events, request.buffer_out + 0xc*i + 4); //events
Memory::Write_U32(revents, request.buffer_out + 0xc * i + 8); // revents Memory::Write_U32(revents, request.buffer_out + 0xc * i + 8); // revents
DEBUG_LOG(IOS_NET, "IOCTL_SO_POLL socket %d wevents %08X events %08X revents %08X", i, DEBUG_LOG(IOS_NET, "IOCTL_SO_POLL socket %d wevents %08X events %08X revents %08X", i, revents,
revents, ufds[i].events, ufds[i].revents); ufds[i].events, ufds[i].revents);
} }
return_value = ret; return GetDefaultReply(ret);
break;
} }
case IOCTL_SO_GETHOSTBYNAME: IPCCommandResult NetIPTop::GetHostByName(const IOCtlRequest& request)
{ {
if (request.buffer_out_size != 0x460) if (request.buffer_out_size != 0x460)
{ {
ERROR_LOG(IOS_NET, "Bad buffer size for IOCTL_SO_GETHOSTBYNAME"); ERROR_LOG(IOS_NET, "Bad buffer size for IOCTL_SO_GETHOSTBYNAME");
return_value = -1; return GetDefaultReply(-1);
break;
} }
std::string hostname = Memory::GetString(request.buffer_in); std::string hostname = Memory::GetString(request.buffer_in);
@ -550,8 +621,9 @@ IPCCommandResult NetIPTop::IOCtl(const IOCtlRequest& request)
hostname.c_str(), request.buffer_in, request.buffer_in_size, request.buffer_out, hostname.c_str(), request.buffer_in, request.buffer_in_size, request.buffer_out,
request.buffer_out_size); request.buffer_out_size);
if (remoteHost) if (remoteHost == nullptr)
{ return GetDefaultReply(-1);
for (int i = 0; remoteHost->h_aliases[i]; ++i) for (int i = 0; remoteHost->h_aliases[i]; ++i)
{ {
DEBUG_LOG(IOS_NET, "alias%i:%s", i, remoteHost->h_aliases[i]); DEBUG_LOG(IOS_NET, "alias%i:%s", i, remoteHost->h_aliases[i]);
@ -560,8 +632,8 @@ IPCCommandResult NetIPTop::IOCtl(const IOCtlRequest& request)
for (int i = 0; remoteHost->h_addr_list[i]; ++i) for (int i = 0; remoteHost->h_addr_list[i]; ++i)
{ {
u32 ip = Common::swap32(*(u32*)(remoteHost->h_addr_list[i])); u32 ip = Common::swap32(*(u32*)(remoteHost->h_addr_list[i]));
std::string ip_s = StringFromFormat("%i.%i.%i.%i", ip >> 24, (ip >> 16) & 0xff, std::string ip_s =
(ip >> 8) & 0xff, ip & 0xff); StringFromFormat("%i.%i.%i.%i", ip >> 24, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
DEBUG_LOG(IOS_NET, "addr%i:%s", i, ip_s.c_str()); DEBUG_LOG(IOS_NET, "addr%i:%s", i, ip_s.c_str());
} }
@ -573,8 +645,7 @@ IPCCommandResult NetIPTop::IOCtl(const IOCtlRequest& request)
if (name_length > (GETHOSTBYNAME_IP_LIST_OFFSET - GETHOSTBYNAME_STRUCT_SIZE)) if (name_length > (GETHOSTBYNAME_IP_LIST_OFFSET - GETHOSTBYNAME_STRUCT_SIZE))
{ {
ERROR_LOG(IOS_NET, "Hostname too long in IOCTL_SO_GETHOSTBYNAME"); ERROR_LOG(IOS_NET, "Hostname too long in IOCTL_SO_GETHOSTBYNAME");
return_value = -1; return GetDefaultReply(-1);
break;
} }
Memory::CopyToEmu(request.buffer_out + GETHOSTBYNAME_STRUCT_SIZE, remoteHost->h_name, Memory::CopyToEmu(request.buffer_out + GETHOSTBYNAME_STRUCT_SIZE, remoteHost->h_name,
name_length); name_length);
@ -598,8 +669,7 @@ IPCCommandResult NetIPTop::IOCtl(const IOCtlRequest& request)
// This must be exact: PPC code to convert the struct hardcodes // This must be exact: PPC code to convert the struct hardcodes
// this offset. // this offset.
static const u32 GETHOSTBYNAME_IP_PTR_LIST_OFFSET = 0x340; static const u32 GETHOSTBYNAME_IP_PTR_LIST_OFFSET = 0x340;
Memory::Write_U32(request.buffer_out + GETHOSTBYNAME_IP_PTR_LIST_OFFSET, Memory::Write_U32(request.buffer_out + GETHOSTBYNAME_IP_PTR_LIST_OFFSET, request.buffer_out + 12);
request.buffer_out + 12);
for (u32 i = 0; i < num_ip_addr; ++i) for (u32 i = 0; i < num_ip_addr; ++i)
{ {
u32 addr = request.buffer_out + GETHOSTBYNAME_IP_PTR_LIST_OFFSET + i * 4; u32 addr = request.buffer_out + GETHOSTBYNAME_IP_PTR_LIST_OFFSET + i * 4;
@ -612,45 +682,28 @@ IPCCommandResult NetIPTop::IOCtl(const IOCtlRequest& request)
request.buffer_out + 4); request.buffer_out + 4);
// Returned struct must be ipv4. // Returned struct must be ipv4.
_assert_msg_(IOS_NET, _assert_msg_(IOS_NET, remoteHost->h_addrtype == AF_INET && remoteHost->h_length == sizeof(u32),
remoteHost->h_addrtype == AF_INET && remoteHost->h_length == sizeof(u32),
"returned host info is not IPv4"); "returned host info is not IPv4");
Memory::Write_U16(AF_INET, request.buffer_out + 8); Memory::Write_U16(AF_INET, request.buffer_out + 8);
Memory::Write_U16(sizeof(u32), request.buffer_out + 10); Memory::Write_U16(sizeof(u32), request.buffer_out + 10);
return_value = 0; return GetDefaultReply(0);
} }
else
IPCCommandResult NetIPTop::ICMPCancel(const IOCtlRequest& request)
{ {
return_value = -1;
}
break;
}
case IOCTL_SO_ICMPCANCEL:
ERROR_LOG(IOS_NET, "IOCTL_SO_ICMPCANCEL"); ERROR_LOG(IOS_NET, "IOCTL_SO_ICMPCANCEL");
return GetDefaultReply(0);
default:
request.DumpUnknown(GetDeviceName(), LogTypes::IOS_NET);
} }
return GetDefaultReply(return_value); IPCCommandResult NetIPTop::GetInterfaceOpt(const IOCtlVRequest& request)
} {
const u32 param = Memory::Read_U32(request.in_vectors[0].address);
const u32 param2 = Memory::Read_U32(request.in_vectors[0].address + 4);
const u32 param3 = Memory::Read_U32(request.io_vectors[0].address);
const u32 param4 = Memory::Read_U32(request.io_vectors[1].address);
u32 param5 = 0;
IPCCommandResult NetIPTop::IOCtlV(const IOCtlVRequest& request)
{
s32 return_value = 0;
u32 param = 0, param2 = 0, param3, param4, param5 = 0;
switch (request.request)
{
case IOCTLV_SO_GETINTERFACEOPT:
{
param = Memory::Read_U32(request.in_vectors[0].address);
param2 = Memory::Read_U32(request.in_vectors[0].address + 4);
param3 = Memory::Read_U32(request.io_vectors[0].address);
param4 = Memory::Read_U32(request.io_vectors[1].address);
if (request.io_vectors[0].size >= 8) if (request.io_vectors[0].size >= 8)
{ {
param5 = Memory::Read_U32(request.io_vectors[0].address + 4); param5 = Memory::Read_U32(request.io_vectors[0].address + 4);
@ -709,13 +762,11 @@ IPCCommandResult NetIPTop::IOCtlV(const IOCtlVRequest& request)
AdapterList->OperStatus == IfOperStatusUp) AdapterList->OperStatus == IfOperStatusUp)
{ {
INFO_LOG(IOS_NET, "Name of valid interface: %S", AdapterList->FriendlyName); INFO_LOG(IOS_NET, "Name of valid interface: %S", AdapterList->FriendlyName);
INFO_LOG(IOS_NET, "DNS: %u.%u.%u.%u", INFO_LOG(
(unsigned char) IOS_NET, "DNS: %u.%u.%u.%u",
AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[2], (unsigned char)AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[2],
(unsigned char) (unsigned char)AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[3],
AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[3], (unsigned char)AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[4],
(unsigned char)
AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[4],
(unsigned char) (unsigned char)
AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[5]); AdapterList->FirstDnsServerAddress->Address.lpSockaddr->sa_data[5]);
address = Common::swap32( address = Common::swap32(
@ -768,25 +819,27 @@ IPCCommandResult NetIPTop::IOCtlV(const IOCtlVRequest& request)
ERROR_LOG(IOS_NET, "Unknown param2: %08X", param2); ERROR_LOG(IOS_NET, "Unknown param2: %08X", param2);
break; break;
} }
break;
return GetDefaultReply(0);
} }
case IOCTLV_SO_SENDTO:
IPCCommandResult NetIPTop::SendTo(const IOCtlVRequest& request)
{ {
u32 fd = Memory::Read_U32(request.in_vectors[1].address); u32 fd = Memory::Read_U32(request.in_vectors[1].address);
WiiSockMan& sm = WiiSockMan::GetInstance(); WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(fd, request, IOCTLV_SO_SENDTO); sm.DoSock(fd, request, IOCTLV_SO_SENDTO);
return GetNoReply(); return GetNoReply();
break;
} }
case IOCTLV_SO_RECVFROM:
IPCCommandResult NetIPTop::RecvFrom(const IOCtlVRequest& request)
{ {
u32 fd = Memory::Read_U32(request.in_vectors[0].address); u32 fd = Memory::Read_U32(request.in_vectors[0].address);
WiiSockMan& sm = WiiSockMan::GetInstance(); WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(fd, request, IOCTLV_SO_RECVFROM); sm.DoSock(fd, request, IOCTLV_SO_RECVFROM);
return GetNoReply(); return GetNoReply();
break;
} }
case IOCTLV_SO_GETADDRINFO:
IPCCommandResult NetIPTop::GetAddressInfo(const IOCtlVRequest& request)
{ {
addrinfo hints; addrinfo hints;
@ -828,8 +881,7 @@ IPCCommandResult NetIPTop::IOCtlV(const IOCtlVRequest& request)
u32 sockoffset = addr + 0x460; u32 sockoffset = addr + 0x460;
if (ret == 0) if (ret == 0)
{ {
for (addrinfo* result_iter = result; result_iter != nullptr; for (addrinfo* result_iter = result; result_iter != nullptr; result_iter = result_iter->ai_next)
result_iter = result_iter->ai_next)
{ {
Memory::Write_U32(result_iter->ai_flags, addr); Memory::Write_U32(result_iter->ai_flags, addr);
Memory::Write_U32(result_iter->ai_family, addr + 0x04); Memory::Write_U32(result_iter->ai_family, addr + 0x04);
@ -875,10 +927,10 @@ IPCCommandResult NetIPTop::IOCtlV(const IOCtlVRequest& request)
} }
request.Dump(GetDeviceName(), LogTypes::IOS_NET, LogTypes::LINFO); request.Dump(GetDeviceName(), LogTypes::IOS_NET, LogTypes::LINFO);
return_value = ret; return GetDefaultReply(ret);
break;
} }
case IOCTLV_SO_ICMPPING:
IPCCommandResult NetIPTop::ICMPPing(const IOCtlVRequest& request)
{ {
struct struct
{ {
@ -921,7 +973,9 @@ IPCCommandResult NetIPTop::IOCtlV(const IOCtlVRequest& request)
s32 icmp_length = sizeof(data); s32 icmp_length = sizeof(data);
if (request.in_vectors.size() > 1 && request.in_vectors[1].size == sizeof(data)) if (request.in_vectors.size() > 1 && request.in_vectors[1].size == sizeof(data))
{
Memory::CopyFromEmu(data, request.in_vectors[1].address, request.in_vectors[1].size); Memory::CopyFromEmu(data, request.in_vectors[1].address, request.in_vectors[1].size);
}
else else
{ {
// TODO sequence number is incremented either statically, by // TODO sequence number is incremented either statically, by
@ -938,19 +992,7 @@ IPCCommandResult NetIPTop::IOCtlV(const IOCtlVRequest& request)
} }
// TODO proper error codes // TODO proper error codes
return_value = 0; return GetDefaultReply(0);
break;
}
default:
request.DumpUnknown(GetDeviceName(), LogTypes::IOS_NET);
}
return GetDefaultReply(return_value);
}
void NetIPTop::Update()
{
WiiSockMan::GetInstance().Update();
} }
} // namespace Device } // namespace Device
} // namespace HLE } // namespace HLE

View File

@ -70,6 +70,31 @@ public:
void Update() override; void Update() override;
private: private:
IPCCommandResult StartUp(const IOCtlRequest& request);
IPCCommandResult Socket(const IOCtlRequest& request);
IPCCommandResult ICMPSocket(const IOCtlRequest& request);
IPCCommandResult Close(const IOCtlRequest& request);
IPCCommandResult DoSock(const IOCtlRequest& request);
IPCCommandResult Shutdown(const IOCtlRequest& request);
IPCCommandResult Listen(const IOCtlRequest& request);
IPCCommandResult GetSockOpt(const IOCtlRequest& request);
IPCCommandResult SetSockOpt(const IOCtlRequest& request);
IPCCommandResult GetSockName(const IOCtlRequest& request);
IPCCommandResult GetPeerName(const IOCtlRequest& request);
IPCCommandResult GetHostID(const IOCtlRequest& request);
IPCCommandResult InetAToN(const IOCtlRequest& request);
IPCCommandResult InetPToN(const IOCtlRequest& request);
IPCCommandResult InetNToP(const IOCtlRequest& request);
IPCCommandResult Poll(const IOCtlRequest& request);
IPCCommandResult GetHostByName(const IOCtlRequest& request);
IPCCommandResult ICMPCancel(const IOCtlRequest& request);
IPCCommandResult GetInterfaceOpt(const IOCtlVRequest& request);
IPCCommandResult SendTo(const IOCtlVRequest& request);
IPCCommandResult RecvFrom(const IOCtlVRequest& request);
IPCCommandResult GetAddressInfo(const IOCtlVRequest& request);
IPCCommandResult ICMPPing(const IOCtlVRequest& request);
#ifdef _WIN32 #ifdef _WIN32
WSADATA InitData; WSADATA InitData;
#endif #endif