-
Notifications
You must be signed in to change notification settings - Fork 0
/
checksum.c
118 lines (69 loc) · 2.22 KB
/
checksum.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
/*
These functions are unmodified copies from this implementation:
http://www.roman10.net/2011/11/27/how-to-calculate-iptcpudp-checksumpart-2-implementation/
from Liu Feipeng
*/
#include "checksum.h"
static unsigned short compute_checksum(unsigned short *addr, unsigned int count) {
register 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);
}
void compute_ip_checksum(struct ip* iphdrp){
iphdrp->ip_sum = 0x0000;
iphdrp->ip_sum = compute_checksum((unsigned short*)iphdrp, iphdrp->ip_hl<<2);
}
// Build IPv4 UDP pseudo-header and call checksum function.
u_int16_t compute_udp_checksum(struct ip *pIph, unsigned short *ipPayload) {
register unsigned long sum = 0;
struct udphdr* udphdrp = (struct udphdr*)(ipPayload);
unsigned short udpLen = htons(udphdrp->uh_sum);
//printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~udp len=%d\n", udpLen);
//add the pseudo header
//printf("add pseudo header\n");
//the source ip
sum += (pIph->ip_src.s_addr>>16)&0xFFFF;
sum += (pIph->ip_src.s_addr)&0xFFFF;
//the dest ip
sum += (pIph->ip_dst.s_addr>>16)&0xFFFF;
sum += (pIph->ip_dst.s_addr)&0xFFFF;
//protocol and reserved: 17
sum += htons(IPPROTO_UDP);
//the length
sum += udphdrp->uh_ulen;
//add the IP payload
//printf("add ip payload\n");
//initialize checksum to 0
udphdrp->uh_sum = 0;
while (udpLen > 1) {
sum += * ipPayload++;
udpLen -= 2;
}
//if any bytes left, pad the bytes and add
if(udpLen > 0) {
//printf("+++++++++++++++padding: %d\n", udpLen);
sum += ((*ipPayload)&htons(0xFF00));
}
//Fold sum to 16 bits: add carrier to result
//printf("add carrier\n");
while (sum>>16) {
sum = (sum & 0xffff) + (sum >> 16);
}
//printf("one's complement\n");
sum = ~sum;
//set computation result
return ((unsigned short)sum == 0x0000)?0xFFFF:(unsigned short)sum;
}