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
mod packet;
pub use self::packet::Packet;
mod builder;
pub use self::builder::Builder;
use crate::ip;
use crate::ip::Protocol;
pub fn checksum<B: AsRef<[u8]>>(ip: &ip::Packet<B>, buffer: &[u8]) -> u16 {
use std::io::Cursor;
use byteorder::{WriteBytesExt, ReadBytesExt, BigEndian};
let mut prefix = [0u8; 40];
match *ip {
ip::Packet::V4(ref packet) => {
prefix[0 .. 4].copy_from_slice(&packet.source().octets());
prefix[4 .. 8].copy_from_slice(&packet.destination().octets());
prefix[9] = Protocol::Udp.into();
Cursor::new(&mut prefix[10 ..])
.write_u16::<BigEndian>(buffer.len() as u16).unwrap();
}
ip::Packet::V6(ref _packet) => {
unimplemented!();
}
};
let mut result = 0xffffu32;
let mut buffer = Cursor::new(buffer);
let mut prefix = match *ip {
ip::Packet::V4(_) =>
Cursor::new(&prefix[0 .. 12]),
ip::Packet::V6(_) =>
Cursor::new(&prefix[0 .. 40]),
};
while let Ok(value) = prefix.read_u16::<BigEndian>() {
result += u32::from(value);
if result > 0xffff {
result -= 0xffff;
}
}
while let Ok(value) = buffer.read_u16::<BigEndian>() {
if buffer.position() == 8 {
continue;
}
result += u32::from(value);
if result > 0xffff {
result -= 0xffff;
}
}
!result as u16
}