[rustack] wire::ipv4: Use wire::util::packet
Change-Id: I73f5cf6b5117e4e37bd52a9110992750222bc53f
diff --git a/bin/recovery-netstack/src/wire/ipv4.rs b/bin/recovery-netstack/src/wire/ipv4.rs
index 6ad77c4..9ac3a15 100644
--- a/bin/recovery-netstack/src/wire/ipv4.rs
+++ b/bin/recovery-netstack/src/wire/ipv4.rs
@@ -3,10 +3,12 @@
// found in the LICENSE file.
use byteorder::{BigEndian, ByteOrder};
-use zerocopy::{AsBytes, ByteSlice, FromBytes, LayoutVerified};
+use zerocopy::{AsBytes, ByteSlice, FromBytes, Unaligned};
use ip::{Ipv4Addr, Ipv4Option};
-use wire::util::{Checksum, Options, PacketFormat};
+use wire::util::packet;
+use wire::util::packet::{PacketWithOptions, PacketWithOptionsParseErr};
+use wire::util::{Checksum, OptionParseErr, Options, PacketFormat};
use self::options::Ipv4OptionImpl;
@@ -35,6 +37,7 @@
unsafe impl FromBytes for HeaderPrefix {}
unsafe impl AsBytes for HeaderPrefix {}
+unsafe impl Unaligned for HeaderPrefix {}
impl HeaderPrefix {
fn version(&self) -> u8 {
@@ -46,144 +49,155 @@
}
}
+impl packet::Header for HeaderPrefix {
+ type Error = ();
+
+ fn total_packet_len(&self) -> Result<Option<usize>, ()> {
+ Ok(Some(BigEndian::read_u16(&self.total_len[..]) as usize))
+ }
+}
+
+impl packet::HeaderPrefix for HeaderPrefix {
+ fn total_header_len(&self) -> Result<usize, ()> {
+ Ok(self.ihl() as usize * 4)
+ }
+}
+
/// An IPv4 packet.
///
/// An `Ipv4Packet` shares its underlying memory with the byte slice it was
/// parsed from or serialized to, meaning that no copying or extra allocation is
/// necessary.
-pub struct Ipv4Packet<B> {
- hdr_prefix: LayoutVerified<B, HeaderPrefix>,
- options: Options<B, Ipv4OptionImpl>,
- body: B,
-}
+// pub struct Ipv4Packet<B> {
+// hdr_prefix: LayoutVerified<B, HeaderPrefix>,
+// options: Options<B, Ipv4OptionImpl>,
+// body: B,
+// }
+
+pub struct Ipv4Packet<B>(PacketWithOptions<B, HeaderPrefix, Options<B, Ipv4OptionImpl>>);
impl<B> PacketFormat for Ipv4Packet<B> {
const MAX_HEADER_BYTES: usize = 60;
const MAX_FOOTER_BYTES: usize = 0;
}
+pub enum Ipv4ParseErr {
+ Packet(PacketWithOptionsParseErr<(), OptionParseErr<()>>),
+ Version,
+ Checksum,
+}
+
impl<B: ByteSlice> Ipv4Packet<B> {
/// Parse an IPv4 packet.
///
/// `parse` parses `bytes` as an IPv4 packet and validates the checksum.
#[cfg_attr(feature = "clippy", allow(needless_pass_by_value))]
- pub fn parse(bytes: B) -> Result<Ipv4Packet<B>, ()> {
+ pub fn parse(bytes: B) -> Result<Ipv4Packet<B>, Ipv4ParseErr> {
// See for details: https://en.wikipedia.org/wiki/IPv4#Header
- let total_len = bytes.len();
- let (hdr_prefix, rest) =
- LayoutVerified::<B, HeaderPrefix>::new_from_prefix(bytes).ok_or(())?;
- let hdr_bytes = (hdr_prefix.ihl() * 4) as usize;
- if hdr_bytes > total_len {
- return Err(());
- }
- let (options, body) = rest.split_at(hdr_bytes - HEADER_PREFIX_SIZE);
- let options = Options::parse(options).map_err(|_| ())?;
- let packet = Ipv4Packet {
- hdr_prefix,
- options,
- body,
- };
- if packet.hdr_prefix.version() != 4 {
- return Err(());
+ let packet: PacketWithOptions<B, HeaderPrefix, _> =
+ PacketWithOptions::parse(bytes).map_err(Ipv4ParseErr::Packet)?;
+ let packet = Ipv4Packet(packet);
+ if packet.0.header_prefix().version() != 4 {
+ return Err(Ipv4ParseErr::Version);
}
if packet.compute_header_checksum() != 0 {
- return Err(());
+ return Err(Ipv4ParseErr::Checksum);
}
Ok(packet)
}
pub fn iter_options<'a>(&'a self) -> impl 'a + Iterator<Item = Ipv4Option> {
- self.options.iter()
+ self.0.options().iter()
}
}
impl<B: ByteSlice> Ipv4Packet<B> {
fn compute_header_checksum(&self) -> u16 {
let mut c = Checksum::new();
- c.add_bytes(self.hdr_prefix.bytes());
- c.add_bytes(self.options.bytes());
+ c.add_bytes(self.0.header_prefix_bytes());
+ c.add_bytes(self.0.options().bytes());
c.sum()
}
pub fn body(&self) -> &[u8] {
- &self.body
+ self.0.body()
}
pub fn version(&self) -> u8 {
- self.hdr_prefix.version()
+ self.0.header_prefix().version()
}
pub fn ihl(&self) -> u8 {
- self.hdr_prefix.ihl()
+ self.0.header_prefix().ihl()
}
pub fn dscp(&self) -> u8 {
- self.hdr_prefix.dscp_ecn >> 2
+ self.0.header_prefix().dscp_ecn >> 2
}
pub fn ecn(&self) -> u8 {
- self.hdr_prefix.dscp_ecn & 3
+ self.0.header_prefix().dscp_ecn & 3
}
pub fn total_length(&self) -> u16 {
- BigEndian::read_u16(&self.hdr_prefix.total_len)
+ BigEndian::read_u16(&self.0.header_prefix().total_len)
}
pub fn id(&self) -> u16 {
- BigEndian::read_u16(&self.hdr_prefix.id)
+ BigEndian::read_u16(&self.0.header_prefix().id)
}
pub fn flags(&self) -> u8 {
- self.hdr_prefix.flags_frag_off[0] >> 5
+ self.0.header_prefix().flags_frag_off[0] >> 5
}
pub fn fragment_offset(&self) -> u16 {
- ((u16::from(self.hdr_prefix.flags_frag_off[0] & 0x1F)) << 8)
- | u16::from(self.hdr_prefix.flags_frag_off[1])
+ ((u16::from(self.0.header_prefix().flags_frag_off[0] & 0x1F)) << 8)
+ | u16::from(self.0.header_prefix().flags_frag_off[1])
}
pub fn ttl(&self) -> u8 {
- self.hdr_prefix.ttl
+ self.0.header_prefix().ttl
}
pub fn proto(&self) -> u8 {
- self.hdr_prefix.proto
+ self.0.header_prefix().proto
}
pub fn hdr_checksum(&self) -> u16 {
- BigEndian::read_u16(&self.hdr_prefix.hdr_checksum)
+ BigEndian::read_u16(&self.0.header_prefix().hdr_checksum)
}
pub fn src_ip(&self) -> Ipv4Addr {
- Ipv4Addr::new(self.hdr_prefix.src_ip)
+ Ipv4Addr::new(self.0.header_prefix().src_ip)
}
pub fn dst_ip(&self) -> Ipv4Addr {
- Ipv4Addr::new(self.hdr_prefix.dst_ip)
+ Ipv4Addr::new(self.0.header_prefix().dst_ip)
}
}
impl<'a> Ipv4Packet<&'a mut [u8]> {
pub fn set_id(&mut self, id: u16) {
- BigEndian::write_u16(&mut self.hdr_prefix.id, id);
+ BigEndian::write_u16(&mut self.0.header_prefix_mut().id, id);
}
pub fn set_ttl(&mut self, ttl: u8) {
- self.hdr_prefix.ttl = ttl;
+ self.0.header_prefix_mut().ttl = ttl;
}
pub fn set_proto(&mut self, proto: u8) {
- self.hdr_prefix.proto = proto;
+ self.0.header_prefix_mut().proto = proto;
}
pub fn set_src_ip(&mut self, src_ip: Ipv4Addr) {
- self.hdr_prefix.src_ip = src_ip.ipv4_bytes();
+ self.0.header_prefix_mut().src_ip = src_ip.ipv4_bytes();
}
pub fn set_dst_ip(&mut self, dst_ip: Ipv4Addr) {
- self.hdr_prefix.dst_ip = dst_ip.ipv4_bytes();
+ self.0.header_prefix_mut().dst_ip = dst_ip.ipv4_bytes();
}
/// Compute and set the header checksum.
@@ -191,9 +205,9 @@
/// Compute the header checksum from the current header state, and set it in
/// the header.
pub fn set_checksum(&mut self) {
- self.hdr_prefix.hdr_checksum = [0, 0];
+ self.0.header_prefix_mut().hdr_checksum = [0, 0];
let c = self.compute_header_checksum();
- BigEndian::write_u16(&mut self.hdr_prefix.hdr_checksum, c);
+ BigEndian::write_u16(&mut self.0.header_prefix_mut().hdr_checksum, c);
}
}