use crate::error::ParseError;
use super::types::{ArpHardwareType, ArpOperation, ArpProtocolType};
pub(super) const PREFIX_LENGTH: usize = 8;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ArpPacket<'a> {
bytes: &'a [u8],
hardware_length: usize,
protocol_length: usize,
}
impl<'a> ArpPacket<'a> {
#[inline]
pub fn parse(bytes: &'a [u8]) -> Result<Self, ParseError> {
let (hardware_length, protocol_length, length) = validate(bytes)?;
Ok(Self {
bytes: &bytes[..length],
hardware_length,
protocol_length,
})
}
#[inline]
pub fn hardware_type(&self) -> ArpHardwareType {
ArpHardwareType::new(u16::from_be_bytes(
self.bytes[0..2].try_into().expect("validated ARP prefix"),
))
}
#[inline]
pub fn protocol_type(&self) -> ArpProtocolType {
ArpProtocolType::new(u16::from_be_bytes(
self.bytes[2..4].try_into().expect("validated ARP prefix"),
))
}
#[inline]
pub fn hardware_address_length(&self) -> u8 {
self.hardware_length as u8
}
#[inline]
pub fn protocol_address_length(&self) -> u8 {
self.protocol_length as u8
}
#[inline]
pub fn hlen(&self) -> u8 {
self.hardware_address_length()
}
#[inline]
pub fn plen(&self) -> u8 {
self.protocol_address_length()
}
#[inline]
pub fn operation(&self) -> ArpOperation {
ArpOperation::new(u16::from_be_bytes(
self.bytes[6..8].try_into().expect("validated ARP prefix"),
))
}
#[inline]
pub fn sender_hardware_address(&self) -> &'a [u8] {
&self.bytes[PREFIX_LENGTH..PREFIX_LENGTH + self.hardware_length]
}
#[inline]
pub fn sender_protocol_address(&self) -> &'a [u8] {
let start = PREFIX_LENGTH + self.hardware_length;
&self.bytes[start..start + self.protocol_length]
}
#[inline]
pub fn target_hardware_address(&self) -> &'a [u8] {
let start = PREFIX_LENGTH + self.hardware_length + self.protocol_length;
&self.bytes[start..start + self.hardware_length]
}
#[inline]
pub fn target_protocol_address(&self) -> &'a [u8] {
let start = PREFIX_LENGTH + 2 * self.hardware_length + self.protocol_length;
&self.bytes[start..]
}
#[inline]
pub fn as_bytes(&self) -> &'a [u8] {
self.bytes
}
}
#[derive(Debug, Eq, PartialEq)]
pub struct ArpPacketMut<'a> {
bytes: &'a mut [u8],
hardware_length: usize,
protocol_length: usize,
}
impl<'a> ArpPacketMut<'a> {
#[inline]
pub fn parse(bytes: &'a mut [u8]) -> Result<Self, ParseError> {
let (hardware_length, protocol_length, length) = validate(bytes)?;
Ok(Self::from_validated(
&mut bytes[..length],
hardware_length,
protocol_length,
))
}
pub(super) fn from_validated(
bytes: &'a mut [u8],
hardware_length: usize,
protocol_length: usize,
) -> Self {
Self {
bytes,
hardware_length,
protocol_length,
}
}
#[inline]
pub fn hardware_type(&self) -> ArpHardwareType {
ArpHardwareType::new(u16::from_be_bytes(
self.bytes[0..2].try_into().expect("validated ARP prefix"),
))
}
#[inline]
pub fn protocol_type(&self) -> ArpProtocolType {
ArpProtocolType::new(u16::from_be_bytes(
self.bytes[2..4].try_into().expect("validated ARP prefix"),
))
}
#[inline]
pub fn hardware_address_length(&self) -> u8 {
self.hardware_length as u8
}
#[inline]
pub fn protocol_address_length(&self) -> u8 {
self.protocol_length as u8
}
#[inline]
pub fn hlen(&self) -> u8 {
self.hardware_address_length()
}
#[inline]
pub fn plen(&self) -> u8 {
self.protocol_address_length()
}
#[inline]
pub fn operation(&self) -> ArpOperation {
ArpOperation::new(u16::from_be_bytes(
self.bytes[6..8].try_into().expect("validated ARP prefix"),
))
}
#[inline]
pub fn set_hardware_type(&mut self, value: ArpHardwareType) {
self.bytes[0..2].copy_from_slice(&value.raw().to_be_bytes());
}
#[inline]
pub fn set_protocol_type(&mut self, value: ArpProtocolType) {
self.bytes[2..4].copy_from_slice(&value.raw().to_be_bytes());
}
#[inline]
pub fn set_operation(&mut self, value: ArpOperation) {
self.bytes[6..8].copy_from_slice(&value.raw().to_be_bytes());
}
#[inline]
pub fn sender_hardware_address(&self) -> &[u8] {
&self.bytes[PREFIX_LENGTH..PREFIX_LENGTH + self.hardware_length]
}
#[inline]
pub fn sender_hardware_address_mut(&mut self) -> &mut [u8] {
&mut self.bytes[PREFIX_LENGTH..PREFIX_LENGTH + self.hardware_length]
}
#[inline]
pub fn sender_protocol_address(&self) -> &[u8] {
let start = PREFIX_LENGTH + self.hardware_length;
&self.bytes[start..start + self.protocol_length]
}
#[inline]
pub fn sender_protocol_address_mut(&mut self) -> &mut [u8] {
let start = PREFIX_LENGTH + self.hardware_length;
&mut self.bytes[start..start + self.protocol_length]
}
#[inline]
pub fn target_hardware_address(&self) -> &[u8] {
let start = PREFIX_LENGTH + self.hardware_length + self.protocol_length;
&self.bytes[start..start + self.hardware_length]
}
#[inline]
pub fn target_hardware_address_mut(&mut self) -> &mut [u8] {
let start = PREFIX_LENGTH + self.hardware_length + self.protocol_length;
&mut self.bytes[start..start + self.hardware_length]
}
#[inline]
pub fn target_protocol_address(&self) -> &[u8] {
let start = PREFIX_LENGTH + 2 * self.hardware_length + self.protocol_length;
&self.bytes[start..]
}
#[inline]
pub fn target_protocol_address_mut(&mut self) -> &mut [u8] {
let start = PREFIX_LENGTH + 2 * self.hardware_length + self.protocol_length;
&mut self.bytes[start..]
}
#[inline]
pub fn as_bytes(&self) -> &[u8] {
self.bytes
}
#[inline]
pub fn as_bytes_mut(&mut self) -> &mut [u8] {
self.bytes
}
}
#[inline]
fn validate(bytes: &[u8]) -> Result<(usize, usize, usize), ParseError> {
if bytes.len() < PREFIX_LENGTH {
return Err(ParseError::Truncated {
minimum: PREFIX_LENGTH,
available: bytes.len(),
});
}
let hardware_length = bytes[4] as usize;
let protocol_length = bytes[5] as usize;
let length = PREFIX_LENGTH + 2 * hardware_length + 2 * protocol_length;
if bytes.len() < length {
return Err(ParseError::Truncated {
minimum: length,
available: bytes.len(),
});
}
Ok((hardware_length, protocol_length, length))
}