From fc3667c02696e5959b298210880fabfda5d233c0 Mon Sep 17 00:00:00 2001 From: Conrad Pankoff Date: Sat, 10 Aug 2019 13:18:18 +1000 Subject: [PATCH] Kernel: Detect some outgoing TCP connection failures --- Kernel/Net/NetworkTask.cpp | 17 ++++++++++++++++- Kernel/Net/TCPSocket.cpp | 2 ++ Kernel/Net/TCPSocket.h | 28 ++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/Kernel/Net/NetworkTask.cpp b/Kernel/Net/NetworkTask.cpp index a4eaa0ee50..b150353c7d 100644 --- a/Kernel/Net/NetworkTask.cpp +++ b/Kernel/Net/NetworkTask.cpp @@ -410,17 +410,32 @@ void handle_tcp(const IPv4Packet& ipv4_packet) socket->send_tcp_packet(TCPFlags::ACK); socket->set_state(TCPSocket::State::SynReceived); return; - case TCPFlags::SYN | TCPFlags::ACK: + case TCPFlags::ACK | TCPFlags::SYN: socket->set_ack_number(tcp_packet.sequence_number() + payload_size + 1); socket->send_tcp_packet(TCPFlags::ACK); socket->set_state(TCPSocket::State::Established); socket->set_setup_state(Socket::SetupState::Completed); socket->set_connected(true); return; + case TCPFlags::ACK | TCPFlags::FIN: + socket->set_ack_number(tcp_packet.sequence_number() + payload_size + 1); + socket->send_tcp_packet(TCPFlags::ACK); + socket->set_state(TCPSocket::State::Closed); + socket->set_error(TCPSocket::Error::FINDuringConnect); + socket->set_setup_state(Socket::SetupState::Completed); + return; + case TCPFlags::ACK | TCPFlags::RST: + socket->set_ack_number(tcp_packet.sequence_number() + payload_size + 1); + socket->send_tcp_packet(TCPFlags::ACK); + socket->set_state(TCPSocket::State::Closed); + socket->set_error(TCPSocket::Error::RSTDuringConnect); + socket->set_setup_state(Socket::SetupState::Completed); + return; default: kprintf("handle_tcp: unexpected flags in SynSent state\n"); socket->send_tcp_packet(TCPFlags::RST); socket->set_state(TCPSocket::State::Closed); + socket->set_error(TCPSocket::Error::UnexpectedFlagsDuringConnect); socket->set_setup_state(Socket::SetupState::Completed); return; } diff --git a/Kernel/Net/TCPSocket.cpp b/Kernel/Net/TCPSocket.cpp index 8f34f6859e..ee7a402015 100644 --- a/Kernel/Net/TCPSocket.cpp +++ b/Kernel/Net/TCPSocket.cpp @@ -274,6 +274,8 @@ KResult TCPSocket::protocol_connect(FileDescription& description, ShouldBlock sh if (current->block(description) == Thread::BlockResult::InterruptedBySignal) return KResult(-EINTR); ASSERT(setup_state() == SetupState::Completed); + if (has_error()) + return KResult(-ECONNREFUSED); return KSuccess; } diff --git a/Kernel/Net/TCPSocket.h b/Kernel/Net/TCPSocket.h index 7afb071cfc..349b16d71f 100644 --- a/Kernel/Net/TCPSocket.h +++ b/Kernel/Net/TCPSocket.h @@ -77,11 +77,38 @@ public: } } + enum class Error { + None, + FINDuringConnect, + RSTDuringConnect, + UnexpectedFlagsDuringConnect, + }; + + static const char* to_string(Error error) + { + switch (error) { + case Error::None: + return "None"; + case Error::FINDuringConnect: + return "FINDuringConnect"; + case Error::RSTDuringConnect: + return "RSTDuringConnect"; + case Error::UnexpectedFlagsDuringConnect: + return "UnexpectedFlagsDuringConnect"; + default: + return "Invalid"; + } + } + State state() const { return m_state; } void set_state(State state); Direction direction() const { return m_direction; } + bool has_error() const { return m_error != Error::None; } + Error error() const { return m_error; } + void set_error(Error error) { m_error = error; } + void set_ack_number(u32 n) { m_ack_number = n; } void set_sequence_number(u32 n) { m_sequence_number = n; } u32 ack_number() const { return m_ack_number; } @@ -118,6 +145,7 @@ private: virtual KResult protocol_listen() override; Direction m_direction { Direction::Unspecified }; + Error m_error { Error::None }; WeakPtr m_adapter; u32 m_sequence_number { 0 }; u32 m_ack_number { 0 };