forked from gopacket/gopacket
-
Notifications
You must be signed in to change notification settings - Fork 0
/
checksum.go
58 lines (53 loc) · 1.98 KB
/
checksum.go
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
// Copyright 2012 Google, Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree.
package gopacket
// ChecksumVerificationResult provides information about a checksum verification.
// The checksums are represented using uint32 to fit even the largest checksums.
// If a checksum is optional and unset, Correct and Actual might mismatch even
// though Valid is true. In this case, Correct is the computed optional checksum
// and Actual is 0.
type ChecksumVerificationResult struct {
// Valid tells whether the checksum verification succeeded.
Valid bool
// Correct is the correct checksum that was expected to be found.
Correct uint32
// Actual is the checksum that was found and which might be wrong.
Actual uint32
}
// ChecksumMismatch provides information about a failed checksum verification
// for a layer.
type ChecksumMismatch struct {
ChecksumVerificationResult
// Layer is the layer whose checksum is invalid.
Layer Layer
// LayerIndex is the index of the layer in the packet.
LayerIndex int
}
// ComputeChecksum computes the internet checksum as defined in RFC1071. The
// passed-in csum is any initial checksum data that's already been computed.
func ComputeChecksum(data []byte, csum uint32) uint32 {
// to handle odd lengths, we loop to length - 1, incrementing by 2, then
// handle the last byte specifically by checking against the original
// length.
length := len(data) - 1
for i := 0; i < length; i += 2 {
// For our test packet, doing this manually is about 25% faster
// (740 ns vs. 1000ns) than doing it by calling binary.BigEndian.Uint16.
csum += uint32(data[i]) << 8
csum += uint32(data[i+1])
}
if len(data)%2 == 1 {
csum += uint32(data[length]) << 8
}
return csum
}
// FoldChecksum folds a 32 bit checksum as defined in RFC1071.
func FoldChecksum(csum uint32) uint16 {
for csum > 0xffff {
csum = (csum >> 16) + (csum & 0xffff)
}
return ^uint16(csum)
}