-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1d2be79
commit 986f619
Showing
2 changed files
with
146 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
pub mod arp; | ||
pub mod ethernet; | ||
pub mod vlan_tagging; | ||
|
||
|