-
Notifications
You must be signed in to change notification settings - Fork 0
/
check_sum_calc.c
132 lines (112 loc) · 3.19 KB
/
check_sum_calc.c
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include "pcap_sniff.h"
/*
* calculate ip checksum (first 20 bytes)
*/
unsigned short CalcIPChecksum(unsigned short *addr, unsigned int count) {
unsigned long sum = 0;
while (count > 1) {
sum += *addr++;
count -= 2;
}
/* if any bytes left, pad the bytes and add */
if(count > 0) {
sum += ((*addr) & htons(0xFF00));
}
/* fold sum to 16 bits: add carrier to result */
while (sum >> 16) {
sum = (sum & 0xffff) + (sum >> 16);
}
/* one's complement */
sum = ~sum;
return ((unsigned short)sum);
}
/* set tcp checksum: given IP header and tcp segment */
unsigned short CalcTCPChecksum(struct iphdr *ip, unsigned short *ip_payload) {
unsigned long sum = 0;
unsigned short tcpLen = ntohs(ip->tot_len) - (ip->ihl<<2);
struct tcphdr *tcphdrp = (struct tcphdr*)(ip_payload);
/* the source ip */
sum += (ip->saddr >> 16) & 0xFFFF;
sum += (ip->saddr) & 0xFFFF;
/* the dest ip */
sum += (ip->daddr >> 16) & 0xFFFF;
sum += (ip->daddr) & 0xFFFF;
/* protocol and reserved: 6 */
sum += htons(IPPROTO_TCP);
/* the length */
sum += htons(tcpLen);
/* add the IP payload */
/* initialize checksum to 0 */
tcphdrp->check = 0;
while (tcpLen > 1) {
sum += * ip_payload++;
tcpLen -= 2;
}
/* if any bytes left, pad the bytes and add */
if(tcpLen > 0) {
sum += ((*ip_payload) & htons(0xFF00));
}
/* fold 32-bit sum to 16 bits: add carrier to result */
while (sum >> 16) {
sum = (sum & 0xffff) + (sum >> 16);
}
sum = ~sum;
/* set computation result */
tcphdrp->check = (unsigned short)sum;
return (unsigned short)sum;
}
/* set udp checksum: given IP header and UDP datagram */
unsigned short CalcUDPChecksum(struct iphdr *ip, unsigned short *ip_payload) {
unsigned long sum = 0;
struct udphdr *udphdrp = (struct udphdr*)(ip_payload);
unsigned short udpLen = htons(udphdrp->len);
/* the source ip */
sum += (ip->saddr>>16)&0xFFFF;
sum += (ip->saddr)&0xFFFF;
/* the dest ip */
sum += (ip->daddr>>16)&0xFFFF;
sum += (ip->daddr)&0xFFFF;
/* protocol and reserved: 17 */
sum += htons(IPPROTO_UDP);
/* the length */
sum += udphdrp->len;
/* initialize checksum to 0 */
udphdrp->check = 0;
while (udpLen > 1) {
sum += * ip_payload++;
udpLen -= 2;
}
/* if any bytes left, pad the bytes and add */
if(udpLen > 0) {
sum += ((*ip_payload)&htons(0xFF00));
}
/* fold sum to 16 bits: add carrier to result */
while (sum>>16) {
sum = (sum & 0xffff) + (sum >> 16);
}
sum = ~sum;
/* set computation result */
return ((unsigned short)sum == 0x0000) ? 0xFFFF : (unsigned short)sum;
}
/*
Function calculate checksum
*/
unsigned short CalcICMPChecksum(unsigned short *ptr, int nbytes) {
unsigned long sum;
u_short oddbyte;
register u_short answer;
sum = 0;
while (nbytes > 1) {
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1) {
oddbyte = 0;
*((u_char *) & oddbyte) = *(u_char *) ptr;
sum += oddbyte;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}