Skip to content

Commit

Permalink
Simplify checksum computation.
Browse files Browse the repository at this point in the history
  • Loading branch information
whitequark committed Dec 13, 2016
1 parent be4ea0a commit 8a3dee0
Showing 3 changed files with 17 additions and 21 deletions.
20 changes: 9 additions & 11 deletions src/wire/icmpv4.rs
Original file line number Diff line number Diff line change
@@ -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[..]);
}

6 changes: 3 additions & 3 deletions src/wire/ip.rs
Original file line number Diff line number Diff line change
@@ -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))
}
12 changes: 5 additions & 7 deletions src/wire/ipv4.rs
Original file line number Diff line number Diff line change
@@ -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)
}

0 comments on commit 8a3dee0

Please sign in to comment.