diff options
author | brapru <brapru@pm.me> | 2021-07-18 18:19:25 -0400 |
---|---|---|
committer | Gunnar Beutner <gunnar@beutner.name> | 2021-08-02 02:45:56 +0200 |
commit | 9c3e6f3f63cc0de2175d3ef8431ce91ebc06504f (patch) | |
tree | 517adfb4a5b7b3a25d76d25487ee0cccea06bf16 | |
parent | 63a15ed19db424c710064bf1e46f3f695ac43e77 (diff) | |
download | serenity-9c3e6f3f63cc0de2175d3ef8431ce91ebc06504f.zip |
Kernel: Send RST/ACK if no socket is available
Previously there was no way for Serenity to send a packet without an
established socket connection, and there was no way to appropriately
respond to a SYN packet on a non-listening port. This patch will respond
to any non-established socket attempts with the appropraite RST/ACK,
letting the client know to close the connection.
-rw-r--r-- | Kernel/Net/NetworkTask.cpp | 50 | ||||
-rw-r--r-- | Kernel/Net/TCPSocket.h | 4 |
2 files changed, 38 insertions, 16 deletions
diff --git a/Kernel/Net/NetworkTask.cpp b/Kernel/Net/NetworkTask.cpp index 745daad68e..3fdeb54de7 100644 --- a/Kernel/Net/NetworkTask.cpp +++ b/Kernel/Net/NetworkTask.cpp @@ -30,6 +30,7 @@ static void handle_icmp(EthernetFrameHeader const&, IPv4Packet const&, Time cons static void handle_udp(IPv4Packet const&, Time const& packet_timestamp); static void handle_tcp(IPv4Packet const&, Time const& packet_timestamp); static void send_delayed_tcp_ack(RefPtr<TCPSocket> socket); +static void send_tcp_rst(IPv4Packet const& ipv4_packet, TCPPacket const& tcp_packet, RefPtr<NetworkAdapter> adapter); static void flush_delayed_tcp_acks(); static void retransmit_tcp_packets(); @@ -328,6 +329,39 @@ void flush_delayed_tcp_acks() } } +void send_tcp_rst(IPv4Packet const& ipv4_packet, TCPPacket const& tcp_packet, RefPtr<NetworkAdapter> adapter) +{ + auto routing_decision = route_to(ipv4_packet.source(), ipv4_packet.destination(), adapter); + if (routing_decision.is_zero()) + return; + + auto ipv4_payload_offset = routing_decision.adapter->ipv4_payload_offset(); + + const size_t options_size = 0; + const size_t tcp_header_size = sizeof(TCPPacket) + options_size; + const size_t buffer_size = ipv4_payload_offset + tcp_header_size; + + auto packet = routing_decision.adapter->acquire_packet_buffer(buffer_size); + if (!packet) + return; + routing_decision.adapter->fill_in_ipv4_header(*packet, ipv4_packet.destination(), + routing_decision.next_hop, ipv4_packet.source(), IPv4Protocol::TCP, + buffer_size - ipv4_payload_offset, 64); + memset(packet->buffer.data() + ipv4_payload_offset, 0, sizeof(TCPPacket)); + auto& rst_packet = *(TCPPacket*)(packet->buffer.data() + ipv4_payload_offset); + rst_packet.set_source_port(tcp_packet.destination_port()); + rst_packet.set_destination_port(tcp_packet.source_port()); + rst_packet.set_window_size(0); + rst_packet.set_sequence_number(0); + rst_packet.set_ack_number(tcp_packet.sequence_number() + 1); + rst_packet.set_data_offset(tcp_header_size / sizeof(u32)); + rst_packet.set_flags(TCPFlags::RST | TCPFlags::ACK); + rst_packet.set_checksum(TCPSocket::compute_tcp_checksum(ipv4_packet.source(), ipv4_packet.destination(), rst_packet, 0)); + + routing_decision.adapter->send_packet({ packet->buffer.data(), packet->buffer.size() }); + routing_decision.adapter->release_packet_buffer(*packet); +} + void handle_tcp(IPv4Packet const& ipv4_packet, Time const& packet_timestamp) { if (ipv4_packet.payload_size() < sizeof(TCPPacket)) { @@ -377,20 +411,8 @@ void handle_tcp(IPv4Packet const& ipv4_packet, Time const& packet_timestamp) auto socket = TCPSocket::from_tuple(tuple); if (!socket) { - dbgln("handle_tcp: No TCP socket for tuple {}", tuple.to_string()); - dbgln("handle_tcp: source={}:{}, destination={}:{}, seq_no={}, ack_no={}, flags={:#04x} ({}{}{}{}), window_size={}, payload_size={}", - ipv4_packet.source().to_string(), tcp_packet.source_port(), - ipv4_packet.destination().to_string(), - tcp_packet.destination_port(), - tcp_packet.sequence_number(), - tcp_packet.ack_number(), - tcp_packet.flags(), - tcp_packet.has_syn() ? "SYN " : "", - tcp_packet.has_ack() ? "ACK " : "", - tcp_packet.has_fin() ? "FIN " : "", - tcp_packet.has_rst() ? "RST " : "", - tcp_packet.window_size(), - payload_size); + dbgln("handle_tcp: No TCP socket for tuple {}. Sending RST.", tuple.to_string()); + send_tcp_rst(ipv4_packet, tcp_packet, adapter); return; } diff --git a/Kernel/Net/TCPSocket.h b/Kernel/Net/TCPSocket.h index 94dbe9885d..83a74abdb6 100644 --- a/Kernel/Net/TCPSocket.h +++ b/Kernel/Net/TCPSocket.h @@ -159,6 +159,8 @@ public: virtual bool can_write(const FileDescription&, size_t) const override; + static NetworkOrdered<u16> compute_tcp_checksum(IPv4Address const& source, IPv4Address const& destination, TCPPacket const&, u16 payload_size); + protected: void set_direction(Direction direction) { m_direction = direction; } @@ -166,8 +168,6 @@ private: explicit TCPSocket(int protocol); virtual StringView class_name() const override { return "TCPSocket"; } - static NetworkOrdered<u16> compute_tcp_checksum(const IPv4Address& source, const IPv4Address& destination, const TCPPacket&, u16 payload_size); - virtual void shut_down_for_writing() override; virtual KResultOr<size_t> protocol_receive(ReadonlyBytes raw_ipv4_packet, UserOrKernelBuffer& buffer, size_t buffer_size, int flags) override; |