Simplify checksum computation.

v0.7.x
whitequark 2016-12-13 17:31:08 +00:00
parent 1c616218a1
commit 53309f8271
3 changed files with 17 additions and 21 deletions

View File

@ -2,7 +2,7 @@ use core::{cmp, fmt};
use byteorder::{ByteOrder, NetworkEndian};
use Error;
use super::ip::rfc1071_checksum;
use super::ip::checksum;
enum_with_unknown! {
/// Internet protocol control message type.
@ -216,11 +216,8 @@ impl<T: AsRef<[u8]>> Packet<T> {
/// Validate the header checksum.
pub fn verify_checksum(&self) -> bool {
let checksum = {
let data = self.buffer.as_ref();
rfc1071_checksum(field::CHECKSUM.start, data)
};
self.checksum() == checksum
let data = self.buffer.as_ref();
checksum(data) == !0
}
}
@ -285,9 +282,10 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
/// Compute and fill in the header checksum.
pub fn fill_checksum(&mut self) {
self.set_checksum(0);
let checksum = {
let data = self.buffer.as_ref();
rfc1071_checksum(field::CHECKSUM.start, data)
!checksum(data)
};
self.set_checksum(checksum)
}
@ -411,7 +409,7 @@ mod test {
use super::*;
static ECHO_PACKET_BYTES: [u8; 12] =
[0x08, 0x00, 0x39, 0xfe,
[0x08, 0x00, 0x8e, 0xfe,
0x12, 0x34, 0xab, 0xcd,
0xaa, 0x00, 0x00, 0xff];
@ -423,11 +421,11 @@ mod test {
let packet = Packet::new(&ECHO_PACKET_BYTES[..]).unwrap();
assert_eq!(packet.msg_type(), Type::EchoRequest);
assert_eq!(packet.msg_code(), 0);
assert_eq!(packet.checksum(), 0x39fe);
assert_eq!(packet.checksum(), 0x8efe);
assert_eq!(packet.echo_ident(), 0x1234);
assert_eq!(packet.echo_seq_no(), 0xabcd);
assert_eq!(packet.verify_checksum(), true);
assert_eq!(packet.data(), &ECHO_DATA_BYTES[..]);
assert_eq!(packet.verify_checksum(), true);
}
#[test]
@ -438,8 +436,8 @@ mod test {
packet.set_msg_code(0);
packet.set_echo_ident(0x1234);
packet.set_echo_seq_no(0xabcd);
packet.fill_checksum();
packet.data_mut().copy_from_slice(&ECHO_DATA_BYTES[..]);
packet.fill_checksum();
assert_eq!(&packet.into_inner()[..], &ECHO_PACKET_BYTES[..]);
}

View File

@ -21,12 +21,12 @@ impl fmt::Display for ProtocolType {
}
}
pub fn rfc1071_checksum(checksum_at: usize, data: &[u8]) -> u16 {
/// Compute an RFC 1071 compliant checksum (without the final complement).
pub fn checksum(data: &[u8]) -> u16 {
let mut accum: u32 = 0;
for i in (0..data.len()).step_by(2) {
if i == checksum_at { continue }
let word = NetworkEndian::read_u16(&data[i..i + 2]) as u32;
accum += word;
}
!(((accum >> 16) as u16) + (accum as u16))
(((accum >> 16) as u16) + (accum as u16))
}

View File

@ -2,7 +2,7 @@ use core::fmt;
use byteorder::{ByteOrder, NetworkEndian};
use Error;
use super::ip::rfc1071_checksum;
use super::ip::checksum;
pub use super::InternetProtocolType as ProtocolType;
@ -211,11 +211,8 @@ impl<T: AsRef<[u8]>> Packet<T> {
/// Validate the header checksum.
pub fn verify_checksum(&self) -> bool {
let checksum = {
let data = self.buffer.as_ref();
rfc1071_checksum(field::CHECKSUM.start, &data[..self.header_len() as usize])
};
self.checksum() == checksum
let data = self.buffer.as_ref();
checksum(&data[..self.header_len() as usize]) == !0
}
}
@ -342,9 +339,10 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
/// Compute and fill in the header checksum.
pub fn fill_checksum(&mut self) {
self.set_checksum(0);
let checksum = {
let data = self.buffer.as_ref();
rfc1071_checksum(field::CHECKSUM.start, &data[..self.header_len() as usize])
!checksum(&data[..self.header_len() as usize])
};
self.set_checksum(checksum)
}