Understanding SYN_RECV status with Linux kernel source code

Source: Internet
Author: User
Use the Linux kernel source code to understand SYN_RECV status-general Linux technology-Linux programming and kernel information. The following is a detailed description. In the past few days, when I was reading the TCP protocol stack code, I always had a question about tcp_child_process. After reading this article, I had an epiphany.

In tcp_v4_do_rcv, the following code indicates the code used to establish a TCP connection:

If (sk-> sk_state = TCP_LISTEN ){
Struct sock * nsk = tcp_v4_hnd_req (sk, skb );
If (! Nsk)
Goto discard;

If (nsk! = Sk ){
If (tcp_child_process (sk, nsk, skb ))
Goto reset;
Return 0;
}
}

The returned value of tcp_v4_hnd_req is different in different cases.
NULL Error
Nsk = sk receives SYN
Nsk! = Sk receives ACK

When an ACK packet is received, the tcp_v4_hnd_req function creates a new sock structure, sets its initial state to SYN_RECV, and returns the new sock structure.
Call the tcp_child_process function to change the state of the newly created sock to ESTABLISHED.

========================================================== ============================

(The following is based on Linux Kernel 2.4.0)
SYN_RECV status, as the name suggests, is the status that should be set after receiving the SYN packet. The SYN_RECV status is misled by some textbooks. I have always understood that the server should be in this status after receiving the SYN packet. I didn't think about the socket status. Recently, when I checked the implementation of the three-way handshake protocol in the Linux kernel, to think about this problem, we should set the status of the connected socket instead of the status of the listening socket.
Generally, SYN packets are only used in TCP three-way handshake. Common tcp three-way handshake (of course, there are also simultaneous connections,
Semi-join and other situations) are as follows:
1. client SYN package ---> server
2. client <--- SYN Packet/ACK packet server
3. client ACK package ---> server
According to the tcp status chart, the following four statuses are changed:
A. After the client sends the message, the status changes to SYN_SEND;
B. The server receives the SYN Packet and sends the ack confirmation packet and SYN packet. The status changes to SYN_RECV.
C. After the client sends an ack packet, the status changes to ESTABLISHED.
D. After the server sends an ack packet, the status changes to ESTABLISHED.

In the Linux kernel, the preceding statuses correspond to TCP_SYN_SEND, TCP_SYN_RECV, and TCP_ESTABLISHED.
The SYN_RECV status in RFC793 is described as follows:
SYN-RECEIVED-represents waiting for a confirming connection
Request acknowledgment after having both received Ed and sent
Connection request.
It can be seen from the above that this status is set when the local end receives the connection request from the peer end and sends the connection request to the peer end, waiting for the response from the peer end. Therefore, essentially, the connection process is a back-and-forth request response from both parties. It should be called Four handshakes, but common applications mainly use the c/s mode, linux, including most operating systems, encapsulates server-side responses and requests in a package.
However, in the Linux kernel, the connection socket is created and initialized to the TCP_SYN_RECV status after the listening socket receives the ACK package from the client. The following function call relationship is shown:
Tcp_v4_rcv --> tcp_v4_do_rcv --> tcp_v4_hnd_req --> tcp_check_req -->
Tcp_v4_syn_recv_sock --> tcp_create_openreq_child...
Struct sock * tcp_create_openreq_child (struct sock * sk, struct open_request * req, struct sk_buff * skb)
{
Struct sock * newsk = sk_alloc (PF_INET, GFP_ATOMIC, 0);/* Create a sock Connection Structure */

If (newsk! = NULL ){
Struct tcp_opt * newtp;
...
Memcpy (newsk, sk, sizeof (* newsk ));
Newsk-> state = TCP_SYN_RECV;/* set the initial state to SYN_RECV */

// Perform the following operations to initialize the newsk structure:
...
}
This seems to be normal, but another point is that after the server receives the ACK packet, the status should be changed to the connection status, and the socket connection status is TCP_SYN_RECV.
The reason is that the ack package has not been processed yet, ^ _ ^, as follows:
Int tcp_v4_do_rcv (struct sock * sk, struct sk_buff * skb)
{
...
If (sk-> state = TCP_LISTEN) {// The status of the listener socket.
Struct sock * nsk = tcp_v4_hnd_req (sk, skb); // gets the connection socket mentioned above
If (! Nsk)
Goto discard;

If (nsk! = Sk) {// apparently listening and connection socket are different
If (tcp_child_process (sk, nsk, skb) // call tcp_rcv_state_process to set the socket to establish the connection.
Goto reset;
Return 0;
}
}
...
}

It can be seen that in the Linux kernel, The SYN_RECV state is kept for a short period of time (it is also difficult to create conditions to keep this State ), this is why netstat is basically invisible in our actual application.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.