The pseudo header of the TCP check value and calculation of the check Value

Source: Internet
Author: User
Tags htons

Does the check value of the TCP layer still need the metadata of the IP layer, that is, the IP header? If everything is ideal, it is obviously unnecessary, because it violates the principle of layered isolation, the lower layer must not rely on the upper layer, but the upper layer can access the lower layer. Fortunately, the IP information used by TCP/IP is exactly this. According to the packaging principle, IP information is not encapsulated when encapsulated to the TCP layer, but the check value needs to be calculated immediately. Therefore, you must manually construct a pseudo header to indicate the information of the IP layer, how to construct it? When the data arrives at the TCP layer, the user must know where the data is sent. Both the source address and the destination address are available, but the data has not been encapsulated, A simple example is that in the socket program, connect, accept, recvfrom, and sendto will retain the address information, and the pseudo header will also retain the transport layer protocol information, all of this is to make communications more secure and meticulous. Imagine if a man-in-the-middle intercepts an ICMP packet and then changes it to a UDP packet or what happens, this UDP is not random but well-constructed, but it is much more difficult to add a pseudo-header so it can succeed, because the pseudo-header contains protocol fields, in addition to any wrong delivery, the Error Data Length and protocol are detected. Take a look at the pseudo header:

Struct psd_head

{

_ U32 saddr; // source network layer address

_ U32 daddr; // destination network layer address

_ U8 mbz; // 0

_ U8 ptcl; // Transport Layer Protocol

_ Tcpudpl; // Transport Layer length

};

The following is a simple calculation function for checksum and checksum.

Void tcpv4_check_addr (_ 2010* ppkgdata)

{

Char * indata;

_ 16ippktlen, udppktlen, tcppktlen, WD;

_ U32 ipheadlen;

_ U32 sum, I, PL, El;

Struct psd_head PSD;

Struct iphdr * IPD;

Struct tcphdr * tcpd;

Struct udphdr * udpd;

_ 2010* databegin;

Indata = (char *) ppkgdata; // The entire frame starting from Mac.

Ipheadlen = 14 + (indata [14] & 0x0f) * 4; // The length and

Databegin = (_ 2010*) (indata + ipheadlen); // IP data

IPD = (struct iphdr *) (indata + 14); // MAC data

Tcpd = (struct tcphdr *) (indata + ipheadlen); // IP data

Ippktlen = htons (IPD-> tot_len); // The total length of the IP header and IP data

If (IPD-> protocol = 0x6 ){

Tcppktlen = ippktlen + 14-ipheadlen; // The total length of the TCP header and TCP Data

Tcpd-> check = 0;

PSD. saddr = IPD-> saddr; // construct a pseudo Header

PSD. daddr = IPD-> daddr;

PSD. mbz = 0;

PSD. ptcl = 0x06; // The next header of the IP

PSD. tcpudpl = htons (tcppktlen );

Sum = 0;

WD = tcppktlen/2; // each time the data advances 16 bits instead of one byte

For (I = 0; I

Sum + = * databegin;

Databegin ++;

}

El = tcppktlen-WD * 2;

If (El! = 0)

Sum + = (* databegin & 0xff );

WD = sizeof (struct psd_head)/2;

Databegin = (_ 2010*) & PSD. saddr;

For (I = 0; I

Sum + = * databegin;

Databegin ++;

} // The following expression is the sum of high and low 16, and sum/65536 is the high 16 bits: Sum

PL = (sum + sum/65536) & 0 xFFFF;

Sum = 0xffff ^ pl;

Tcpd-> check = (_) sum; // The test and calculation are simple, that is, adding the data and taking the inverse after the data is rolled back.

}

Return;

}

The above algorithm is no longer clear. It even expresses how the offset of the TCP/IP header is calculated. However, this function is not applicable to the actual situation, because in a high-load network environment, in the NAT or data filtering gateway environment, checksum calculation is a very frequent process. Therefore, the C language nature of the above functions will greatly affect the efficiency. Instead, it is implemented through assembly, as in the Linux kernel:

Static inline _ sum16 csum_fold (_ wsum sum)

{

_ ASM __(

"Addl % 1, % 0;/N"

"Adcl $0 xFFFF, % 0;/N"

: "= R" (SUM)

: "R" (_ force u32) sum

"" (_ Force u32) sum & 0xffff0000)

);

Return (_ force _ sum16 )(~ (_ Force u32) sum> 16 );

}

Static inline _ wsum csum_tcpudp_nofold (_ be32 saddr, _ be32 daddr, unsigned short Len, unsigned short proto, _ wsum sum)

{

_ ASM __(

"Addl % 1, % 0;/N"

"Adcl % 2, % 0;/N"

"Adcl % 3, % 0;/N"

"Adcl $0, % 0;/N"

: "= R" (SUM)

: "G" (daddr), "G" (saddr), "G" (LEN + PROTO)

Return sum;

}

Static inline _ sum16 csum_tcpudp_magic (_ be32 saddr, _ be32 daddr, unsigned short Len, unsigned short proto, _ wsum sum)

{

Return csum_fold (csum_tcpudp_nofold (saddr, daddr, Len, proto, sum ));

}

Although a small computing checksum affects the efficiency of network transmission in nature, if the tcpv4_check_addr function is used to calculate the checksum, the efficiency is 10 times slower, but it is replaced by assembly, although the efficiency has declined due to additional absorption, the order of magnitude has not changed.

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.