mirror of
https://github.com/SerenityOS/serenity
synced 2024-09-06 17:06:31 +00:00
Kernel: Return the correct result for FIONREAD on datagram sockets
Before this commit, we only checked the receive buffer on the socket, which is unused on datagram streams. Now we return the actual size of the datagram without the protocol headers, which required the protocol to tell us what the size of the payload is.
This commit is contained in:
parent
e4a1bc1542
commit
3da0c072f4
|
@ -774,7 +774,15 @@ ErrorOr<void> IPv4Socket::ioctl(OpenFileDescription&, unsigned request, Userspac
|
|||
return ioctl_arp();
|
||||
|
||||
case FIONREAD: {
|
||||
int readable = m_receive_buffer->immediately_readable();
|
||||
int readable = 0;
|
||||
if (buffer_mode() == BufferMode::Bytes) {
|
||||
readable = static_cast<int>(m_receive_buffer->immediately_readable());
|
||||
} else {
|
||||
if (m_receive_queue.size() != 0u) {
|
||||
readable = static_cast<int>(TRY(protocol_size(m_receive_queue.first().data->bytes())));
|
||||
}
|
||||
}
|
||||
|
||||
return copy_to_user(static_ptr_cast<int*>(arg), &readable);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ protected:
|
|||
virtual ErrorOr<size_t> protocol_send(const UserOrKernelBuffer&, size_t) { return ENOTIMPL; }
|
||||
virtual ErrorOr<void> protocol_connect(OpenFileDescription&, ShouldBlock) { return {}; }
|
||||
virtual ErrorOr<u16> protocol_allocate_local_port() { return ENOPROTOOPT; }
|
||||
virtual ErrorOr<size_t> protocol_size(ReadonlyBytes /* raw_ipv4_packet */) { return ENOTIMPL; }
|
||||
virtual bool protocol_is_disconnected() const { return false; }
|
||||
|
||||
virtual void shut_down_for_reading() override;
|
||||
|
|
|
@ -161,6 +161,13 @@ ErrorOr<NonnullRefPtr<TCPSocket>> TCPSocket::try_create(int protocol, NonnullOwn
|
|||
return adopt_nonnull_ref_or_enomem(new (nothrow) TCPSocket(protocol, move(receive_buffer), move(scratch_buffer)));
|
||||
}
|
||||
|
||||
ErrorOr<size_t> TCPSocket::protocol_size(ReadonlyBytes raw_ipv4_packet)
|
||||
{
|
||||
auto& ipv4_packet = *reinterpret_cast<const IPv4Packet*>(raw_ipv4_packet.data());
|
||||
auto& tcp_packet = *static_cast<const TCPPacket*>(ipv4_packet.payload());
|
||||
return raw_ipv4_packet.size() - sizeof(IPv4Packet) - tcp_packet.header_size();
|
||||
}
|
||||
|
||||
ErrorOr<size_t> TCPSocket::protocol_receive(ReadonlyBytes raw_ipv4_packet, UserOrKernelBuffer& buffer, size_t buffer_size, [[maybe_unused]] int flags)
|
||||
{
|
||||
auto& ipv4_packet = *reinterpret_cast<const IPv4Packet*>(raw_ipv4_packet.data());
|
||||
|
|
|
@ -174,6 +174,7 @@ private:
|
|||
virtual ErrorOr<size_t> protocol_send(const UserOrKernelBuffer&, size_t) override;
|
||||
virtual ErrorOr<void> protocol_connect(OpenFileDescription&, ShouldBlock) override;
|
||||
virtual ErrorOr<u16> protocol_allocate_local_port() override;
|
||||
virtual ErrorOr<size_t> protocol_size(ReadonlyBytes raw_ipv4_packet) override;
|
||||
virtual bool protocol_is_disconnected() const override;
|
||||
virtual ErrorOr<void> protocol_bind() override;
|
||||
virtual ErrorOr<void> protocol_listen(bool did_allocate_port) override;
|
||||
|
|
|
@ -59,6 +59,13 @@ ErrorOr<NonnullRefPtr<UDPSocket>> UDPSocket::try_create(int protocol, NonnullOwn
|
|||
return adopt_nonnull_ref_or_enomem(new (nothrow) UDPSocket(protocol, move(receive_buffer)));
|
||||
}
|
||||
|
||||
ErrorOr<size_t> UDPSocket::protocol_size(ReadonlyBytes raw_ipv4_packet)
|
||||
{
|
||||
auto& ipv4_packet = *(const IPv4Packet*)(raw_ipv4_packet.data());
|
||||
auto& udp_packet = *static_cast<const UDPPacket*>(ipv4_packet.payload());
|
||||
return udp_packet.length() - sizeof(UDPPacket);
|
||||
}
|
||||
|
||||
ErrorOr<size_t> UDPSocket::protocol_receive(ReadonlyBytes raw_ipv4_packet, UserOrKernelBuffer& buffer, size_t buffer_size, [[maybe_unused]] int flags)
|
||||
{
|
||||
auto& ipv4_packet = *(const IPv4Packet*)(raw_ipv4_packet.data());
|
||||
|
|
|
@ -27,6 +27,7 @@ private:
|
|||
|
||||
virtual ErrorOr<size_t> protocol_receive(ReadonlyBytes raw_ipv4_packet, UserOrKernelBuffer& buffer, size_t buffer_size, int flags) override;
|
||||
virtual ErrorOr<size_t> protocol_send(const UserOrKernelBuffer&, size_t) override;
|
||||
virtual ErrorOr<size_t> protocol_size(ReadonlyBytes raw_ipv4_packet) override;
|
||||
virtual ErrorOr<void> protocol_connect(OpenFileDescription&, ShouldBlock) override;
|
||||
virtual ErrorOr<u16> protocol_allocate_local_port() override;
|
||||
virtual ErrorOr<void> protocol_bind() override;
|
||||
|
|
Loading…
Reference in a new issue