CheckSum的计算方式可以参考如下代码实现:
-
/*
-
* Checksum routine for Internet Protocol family headers (C Version)
-
*/
-
u_short
-
in_cksum(u_short *addr, int len)
-
{
-
int nleft = len;
-
u_short *w = addr;
-
u_short answer;
-
int sum = 0;
-
-
/*
-
* Our algorithm is simple, using a 32 bit accumulator (sum),
-
* we add sequential 16 bit words to it, and at the end, fold
-
* back all the carry bits from the top 16 bits into the lower
-
* 16 bits.
-
*/
-
while (nleft > 1) {
-
sum += *w++;
-
nleft -= 2;
-
}
-
-
/* mop up an odd byte, if necessary */
-
if (nleft == 1)
-
sum += *(u_char *)w;
-
-
/*
-
* add back carry outs from top 16 bits to low 16 bits
-
*/
-
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
-
sum += (sum >> 16); /* add carry */
-
answer = ~sum; /* truncate to 16 bits */
-
return (answer);
-
}
IP/ICMP/TCP/UDP等相关的checksum都可以使用以上函数进行实现。
但是对于不同的数据包,计算checksum的数据段范围还是有所不同的。
ps:
在计算checksum之间:
首先把checksum字段置为0
其次计算checksum获取结果
最后如果计算后的checksum为0,则置checksum字段为0xffff。
IP CheckSum:
只包含Ip Header 20个字节
ICMP CheckSum:
包含Icmp Header(8个字节) + Icmp Data (n个字节)。
对于TCP/UDP的CheckSum,需要包含一个伪Ip Header。
所以TCP/UDP的checksum:
包含伪ip header (12个字节) + header (udp 8个字节, tcp 20个字节) + data(n个字节)
udp的checksum是可选的,但是一般都会进行计算。
以udp为例,以下是udp header:
加上udp的伪ip header:
tcp的也是类似,只是tcp的header和udp的header有所不同。
在计算udp/tcp的checksum时候,因为需要构建ip的伪头部,所以也就需要实现一个带udp/tcp伪头部的udp/tcp header结构:
-
struct udpiphdr {
-
struct ipovly ui_i; /* overlaid ip structure */
-
struct udphdr ui_u; /* udp header */
-
};
-
#define ui_next ui_i.ih_next
-
#define ui_prev ui_i.ih_prev
-
#define ui_x1 ui_i.ih_x1
-
#define ui_pr ui_i.ih_pr
-
#define ui_len ui_i.ih_len
-
#define ui_src ui_i.ih_src
-
#define ui_dst ui_i.ih_dst
-
#define ui_sport ui_u.uh_sport
-
#define ui_dport ui_u.uh_dport
-
#define ui_ulen ui_u.uh_ulen
-
#define ui_sum ui_u.uh_sum
-
-
-
/*
-
* Overlay for ip header used by other protocols (tcp, udp).
-
*/
-
struct ipovly {
-
caddr_t ih_next, ih_prev; /* for protocol sequence q's */
-
u_char ih_x1; /* (unused) */
-
u_char ih_pr; /* protocol */
-
short ih_len; /* protocol length */
-
struct in_addr ih_src; /* source internet address */
-
struct in_addr ih_dst; /* destination internet address */
-
};
阅读(11207) | 评论(0) | 转发(0) |