sys_net/lv2_socket_native: Various fixes

Fix is_socket_connected(always returned false)
Implement SYS_NET_IP_TTLCHK and SYS_NET_IP_MAXTTL
Fix lv2_socket_native::sendmsg, it was only sending the first iovec
Fix sys_net_bnet_sendto addrlen check
Fix assert in lv2_socket_native::recvfrom()
This commit is contained in:
RipleyTom 2026-02-19 23:44:10 +01:00 committed by Elad
parent 53dcf2ba00
commit b7b0e06a54
4 changed files with 33 additions and 25 deletions

View file

@ -992,7 +992,7 @@ error_code sys_net_bnet_sendto(ppu_thread& ppu, s32 s, vm::cptr<void> buf, u32 l
fmt::throw_exception("sys_net_bnet_sendto(s=%d): unknown flags (0x%x)", flags);
}
if (addr && addrlen < 8)
if (addr && addrlen < sizeof(sys_net_sockaddr))
{
sys_net.error("sys_net_bnet_sendto(s=%d): bad addrlen (%u)", s, addrlen);
return -SYS_NET_EINVAL;

View file

@ -107,7 +107,7 @@ enum lv2_ip_option : s32
SYS_NET_IP_MULTICAST_LOOP = 11,
SYS_NET_IP_ADD_MEMBERSHIP = 12,
SYS_NET_IP_DROP_MEMBERSHIP = 13,
SYS_NET_IP_TTLCHK = 23,
SYS_NET_IP_TTLCHK = 23, // This is probably the equivalent of IP_MINTTL on FreeBSD
SYS_NET_IP_MAXTTL = 24,
SYS_NET_IP_DONTFRAG = 26
};

View file

@ -551,12 +551,14 @@ std::tuple<s32, lv2_socket::sockopt_data, u32> lv2_socket_native::getsockopt(s32
}
case SYS_NET_IP_TTLCHK:
{
sys_net.error("sys_net_bnet_getsockopt(IPPROTO_IP, SYS_NET_IP_TTLCHK): stubbed option");
out_val._int = min_ttl;
out_len = sizeof(s32);
return {CELL_OK, out_val, out_len};
}
case SYS_NET_IP_MAXTTL:
{
sys_net.error("sys_net_bnet_getsockopt(IPPROTO_IP, SYS_NET_IP_MAXTTL): stubbed option");
out_val._int = max_ttl;
out_len = sizeof(s32);
return {CELL_OK, out_val, out_len};
}
case SYS_NET_IP_DONTFRAG:
@ -834,13 +836,13 @@ s32 lv2_socket_native::setsockopt(s32 level, s32 optname, const std::vector<u8>&
}
case SYS_NET_IP_TTLCHK:
{
sys_net.error("sys_net_bnet_setsockopt(s=%d, IPPROTO_IP): Stubbed option (0x%x) (SYS_NET_IP_TTLCHK)", lv2_id, optname);
break;
min_ttl = native_int;
return {};
}
case SYS_NET_IP_MAXTTL:
{
sys_net.error("sys_net_bnet_setsockopt(s=%d, IPPROTO_IP): Stubbed option (0x%x) (SYS_NET_IP_MAXTTL)", lv2_id, optname);
break;
max_ttl = native_int;
return {};
}
case SYS_NET_IP_DONTFRAG:
{
@ -910,7 +912,7 @@ std::optional<std::tuple<s32, std::vector<u8>, sys_net_sockaddr>> lv2_socket_nat
{
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
const auto packet = dnshook.get_dns_packet(lv2_id);
ensure(packet.size() < len);
ensure(packet.size() <= len);
memcpy(res_buf.data(), packet.data(), packet.size());
native_addr.ss_family = AF_INET;
(reinterpret_cast<::sockaddr_in*>(&native_addr))->sin_port = std::bit_cast<u16, be_t<u16>>(53); // htons(53)
@ -1069,18 +1071,20 @@ std::optional<s32> lv2_socket_native::sendmsg(s32 flags, const sys_net_msghdr& m
return {-SYS_NET_ECONNRESET};
}
std::vector<u8> buf_copy;
for (int i = 0; i < msg.msg_iovlen; i++)
{
auto iov_base = msg.msg_iov[i].iov_base;
const u32 len = msg.msg_iov[i].iov_len;
const std::vector<u8> buf_copy(vm::_ptr<const char>(iov_base.addr()), vm::_ptr<const char>(iov_base.addr()) + len);
const auto* src = vm::_ptr<const char>(iov_base.addr());
buf_copy.insert(buf_copy.end(), src, src + len);
}
native_result = ::send(native_socket, reinterpret_cast<const char*>(buf_copy.data()), ::narrow<int>(buf_copy.size()), native_flags);
native_result = ::send(native_socket, reinterpret_cast<const char*>(buf_copy.data()), ::narrow<int>(buf_copy.size()), native_flags);
if (native_result >= 0)
{
return {native_result};
}
if (native_result >= 0)
{
return {native_result};
}
result = get_last_error(!so_nbio && (flags & SYS_NET_MSG_DONTWAIT) == 0);
@ -1232,16 +1236,16 @@ bool lv2_socket_native::is_socket_connected()
return false;
}
fd_set readfds, writefds;
struct timeval timeout{0, 0}; // Zero timeout
pollfd pfd{};
pfd.fd = native_socket;
pfd.events = POLLIN | POLLOUT;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_SET(native_socket, &readfds);
FD_SET(native_socket, &writefds);
// Use select to check for readability and writability
const int result = ::select(1, &readfds, &writefds, NULL, &timeout);
// Use poll to check for readability and writability
#ifdef _WIN32
const int result = WSAPoll(&pfd, 1, 0);
#else
const int result = ::poll(&pfd, 1, 0);
#endif
if (result < 0)
{
@ -1250,5 +1254,5 @@ bool lv2_socket_native::is_socket_connected()
}
// Socket is connected if it's readable or writable
return FD_ISSET(native_socket, &readfds) || FD_ISSET(native_socket, &writefds);
return (pfd.revents & (POLLIN | POLLOUT)) != 0;
}

View file

@ -70,6 +70,10 @@ private:
s32 so_reuseaddr = 0;
s32 so_reuseport = 0;
#endif
// Those values come from FreeBSD
s32 min_ttl = 1;
s32 max_ttl = 64;
u16 bound_port = 0;
bool feign_tcp_conn_failure = false; // Savestate load related
};