The following describes the IPv4 ip udp tcp verification and calculation.
Ip verification and calculation are relatively simple. You only need to calculate the ip protocol header;
The IP header is 20 bytes long;
The udp header is 8 bytes long;
Tcp Header Length: 20-20 ~ 60 bytes;
Udp and tcp checksum not only need to load the entire IP protocol (including
Udp/tcp header and udp/tcp protocol load,
A pseudo-protocol header must be calculated first.
Before calculation, the protocol header verification and field must be cleared.
The structure of the pseudo-protocol header is as follows:
0 7 8 15 16 23 24 31
+ -------- +
| Source address |
+ -------- +
| Destination address |
+ -------- +
| Zero | protocol | udp/tcp length |
+ -------- +
Fields in the pseudo-protocol header are also in network byte order;
The following code snippet shows the specific computing methods in GNU/Linux:
// ================================================ ====================
# Include <stdint. h>
# Include <unistd. h>
# Include <sys/socket. h>
# Include <arpa/inet. h>
# Include <netdb. h>
# Include <netinet/in. h>
# Include <netinet/ip. h>
# Include <netinet/ether. h>
# Include <netinet/udp. h>
# Include <netinet/tcp. h>
Struct pseudo _ head {
Uint32_t saddr;
Uint32_t daddr;
Char zero;
Char proto;
Unsigned short len;
};
Int cal_cksum (char * p)
{
Struct iphdr * ip = (struct iphdr *)
(P + sizeof (struct ether_header ));
Cal_ip_cksum (ip );
Struct tcphdr * tcp;
Struct udphdr * udp;
Char * f = (char *) ip + 20;
Switch (ip-> protocol ){
Case IPPROTO_TCP:
Tcp = (struct tcphdr *) f;
Tcp-> check = 0;
Tcp-> check = cal_udptcp_cksum (
(Unsigned short *) f, ip );
Break;
Case IPPROTO_UDP:
Udp = (struct udphdr *) f;
Udp-> check = 0;
Udp-> check = cal_udptcp_cksum (
(Unsigned short *) f, ip );
Break;
Case IPPROTO_IP:
Break;
Default:
Return 1;
}
Return 0;
}
Inline static void cal_ip_cksum (struct iphdr * ip)
{
Ip-> check = 0;
Ip-> check = in_cksum (unsigned short *) ip,
20, 0 );
}
Inline static unsigned short cal_udptcp_cksum (
Unsigned short * p, struct iphdr * ip)
{
Int len = ntohs (ip-> tot_len)-20;
Struct pseudo-head ph;
Ph. len = htons (len );
Ph. saddr = ip-> saddr;
Ph. daddr = ip-> daddr;
Ph. proto = ip-> protocol;
Ph. zero = 0;
Int sum = cal_sum (
(Unsigned short *) & ph, sizeof (ph ));
Return in_cksum (p, len, sum );
}
Unsigned short in_cksum (unsigned short * p,
Int len, int sum)
{
Int n = len;
While (n> 1 ){
Sum + = * p ++;
N-= 2;
}
If (n = 1)
Sum + = * (unsigned char *) p;
Sum = (sum> 16) + (sum & 0 xffff );
Sum + = (sum> 16 );
Unsigned short ret = ~ Sum;
Return ret;
}
Inline static int cal_sum (unsigned short * p, int len)
{
Int sum = 0;
While (len> 0 ){
Sum + = * p ++;
Len-= 2;
}
Return sum;
}
From the column leeshuheng