File: checksum.go

package info (click to toggle)
golang-github-gopacket-gopacket 1.3.0-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 6,004 kB
  • sloc: sh: 301; python: 76; makefile: 10
file content (58 lines) | stat: -rw-r--r-- 2,027 bytes parent folder | download
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)
}