Poison

RST

接收到 RST 包后的处理逻辑位于 tcp_input.c at v4.15

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/* When we get a reset we do this. */
void tcp_reset(struct sock *sk)
{
trace_tcp_receive_reset(sk);

/* We want the right error as BSD sees it (and indeed as we do). */
switch (sk->sk_state) {
case TCP_SYN_SENT:
sk->sk_err = ECONNREFUSED;
break;
case TCP_CLOSE_WAIT:
sk->sk_err = EPIPE;
break;
case TCP_CLOSE:
return;
default:
sk->sk_err = ECONNRESET;
}
/* This barrier is coupled with smp_rmb() in tcp_poll() */
smp_wmb();

tcp_done(sk);

if (!sock_flag(sk, SOCK_DEAD))
sk->sk_error_report(sk);
}

即根据当前 Socket 所处的状态设置不同的 sk->sk_err,随即调用了 tcp_done 函数,源码位于 tcp.c at v4.15:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void tcp_done(struct sock *sk)
{
struct request_sock *req = tcp_sk(sk)->fastopen_rsk;

if (sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV)
TCP_INC_STATS(sock_net(sk), TCP_MIB_ATTEMPTFAILS);

tcp_set_state(sk, TCP_CLOSE);
tcp_clear_xmit_timers(sk);
if (req)
reqsk_fastopen_remove(sk, req, false);

sk->sk_shutdown = SHUTDOWN_MASK;

if (!sock_flag(sk, SOCK_DEAD))
sk->sk_state_change(sk);
else
inet_csk_destroy_sock(sk);
}

即设置 Socket 状态为 CLOSE 并执行相关清理操作。其中 ECONNREFUSED 的注释为 Connection refusedEPIPE 的注释为 Broken pipeECONNRESET 的注释为 Connection reset by peer