Skip to content

Commit

Permalink
add ARP module
Browse files Browse the repository at this point in the history
  • Loading branch information
curranosaurus authored and JulianSchmid committed Nov 28, 2021
1 parent 1d2be79 commit 986f619
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 0 deletions.
145 changes: 145 additions & 0 deletions src/link/arp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
use super::super::*;
use super::ethernet::EtherType;

extern crate byteorder;
use self::byteorder::{BigEndian, ByteOrder, ReadBytesExt};

#[derive(Clone, Debug, Eq, PartialEq)]
/// There are many other possible hardware types, but
/// this library focuses on Ethernet.
pub enum ArpHardwareType {
Ethernet = 0x0001,
}

impl ArpHardwareType {
pub fn from_u16(value: u16) -> Option<ArpHardwareType> {
use self::ArpHardwareType::*;
match value {
0x0001 => Some(Ethernet),
_ => None,
}
}
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ArpOpcode {
Request = 0x0001,
Reply = 0x0002,
}

#[derive(Clone, Debug, Eq, PartialEq, Default)]
pub struct ArpHeader {
pub hardware_type: u16,
pub protocol_type: u16,
pub hardware_len: u8,
pub protocol_len: u8,
pub opcode: u16,
}

impl SerializedSize for ArpHeader {
///Size of the header itself in bytes.
const SERIALIZED_SIZE: usize = 8;
}

impl ArpHeader {
pub fn new(
hardware_type: ArpHardwareType,
protocol_type: EtherType,
opcode: ArpOpcode,
) -> Self {
ArpHeader {
hardware_type: hardware_type as u16,
protocol_type: protocol_type as u16,
hardware_len: 3,
protocol_len: 4, // TODO fix this to allow IPv6
opcode: opcode as u16,
}
}

pub fn header_len(&self) -> usize {
ArpHeader::SERIALIZED_SIZE
}

pub fn total_len(&self) -> usize {
let payload_len = 2 * (self.hardware_len + self.protocol_len);
ArpHeader::SERIALIZED_SIZE + (payload_len as usize)
}

pub fn read_from_slice(slice: &[u8]) -> Result<(ArpHeader, &[u8]), ReadError> {
let header = ArpHeaderSlice::from_slice(slice)?.to_header();
let rest = &slice[header.header_len()..];
Ok((header, rest))
}

pub fn read<T: io::Read + io::Seek + Sized>(reader: &mut T) -> Result<ArpHeader, ReadError> {
let value = reader.read_u8()?;
unimplemented!()
}
}

///A slice containing an arp header of a network packet.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ArpHeaderSlice<'a> {
slice: &'a [u8],
}

impl<'a> ArpHeaderSlice<'a> {
///Creates a slice containing an arp header.
pub fn from_slice(slice: &'a [u8]) -> Result<ArpHeaderSlice<'a>, ReadError> {
// check len
use crate::ReadError::*;
if slice.len() < ArpHeader::SERIALIZED_SIZE {
return Err(UnexpectedEndOfSlice(ArpHeader::SERIALIZED_SIZE));
}

Ok(ArpHeaderSlice {
slice: &slice[..ArpHeader::SERIALIZED_SIZE],
})
}

///Returns the slice containing the arp header
#[inline]
pub fn slice(&self) -> &'a [u8] {
self.slice
}

///Read the "hardware type" field of the ARP header (should usually be 1 for Ethernet)
pub fn hardware_type(&self) -> u16 {
BigEndian::read_u16(self.slice)
}

///Read the "protocol type" field of the ARP header (should be 0x0800 for IPv4, or 0x86DD for IPv6.
pub fn protocol_type(&self) -> u16 {
BigEndian::read_u16(&self.slice[2..])
}

///Read the "hardware length" field of the ARP header (should be 3 for Ethernet).
pub fn hardware_len(&self) -> u8 {
self.slice[4]
}

///Read the "protocol length" field of the ARP header (should be 4 for IPv4, or 16 for IPv6).
pub fn protocol_len(&self) -> u8 {
self.slice[5]
}

///Read the opcode field of the ARP header
pub fn opcode(&self) -> u16 {
BigEndian::read_u16(&self.slice[6..])
}

pub fn total_len(&self) -> usize {
let payload_len = 2 * (self.hardware_len() + self.protocol_len());
ArpHeader::SERIALIZED_SIZE + (payload_len as usize)
}

pub fn to_header(&self) -> ArpHeader {
ArpHeader {
hardware_type: self.hardware_type(),
protocol_type: self.protocol_type(),
hardware_len: self.hardware_len(),
protocol_len: self.protocol_len(),
opcode: self.opcode(),
}
}
}
1 change: 1 addition & 0 deletions src/link/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod arp;
pub mod ethernet;
pub mod vlan_tagging;

Expand Down

0 comments on commit 986f619

Please sign in to comment.