瀏覽代碼

Kernel: Detect some outgoing TCP connection failures

Conrad Pankoff 6 年之前
父節點
當前提交
fc3667c026
共有 3 個文件被更改,包括 46 次插入1 次删除
  1. 16 1
      Kernel/Net/NetworkTask.cpp
  2. 2 0
      Kernel/Net/TCPSocket.cpp
  3. 28 0
      Kernel/Net/TCPSocket.h

+ 16 - 1
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;
         }

+ 2 - 0
Kernel/Net/TCPSocket.cpp

@@ -274,6 +274,8 @@ KResult TCPSocket::protocol_connect(FileDescription& description, ShouldBlock sh
         if (current->block<Thread::ConnectBlocker>(description) == Thread::BlockResult::InterruptedBySignal)
             return KResult(-EINTR);
         ASSERT(setup_state() == SetupState::Completed);
+        if (has_error())
+            return KResult(-ECONNREFUSED);
         return KSuccess;
     }
 

+ 28 - 0
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<NetworkAdapter> m_adapter;
     u32 m_sequence_number { 0 };
     u32 m_ack_number { 0 };