use prelude::*;
pub struct ArpParser;
impl Parsable<PathIp> for ArpParser {
fn parse<'a>(&mut self,
input: &'a [u8],
result: Option<&ParserResultVec>,
_: Option<&mut PathIp>)
-> IResult<&'a [u8], ParserResult> {
do_parse!(input,
expr_opt!(match result {
Some(vector) => match vector.last() {
Some(ref any) => if let Some(eth) = any.downcast_ref::<EthernetPacket>() {
if eth.ethertype == EtherType::Arp {
Some(())
} else {
None
}
} else {
None
},
_ => None,
},
None => Some(()),
}) >>
hw_type: map_opt!(be_u16, ArpHardwareType::from_u16) >>
p_type: map_opt!(be_u16, EtherType::from_u16) >>
hw_len: be_u8 >>
pr_len: be_u8 >>
oper: map_opt!(be_u16, ArpOperation::from_u16) >>
s: take!(6) >>
ip_sender: map!(be_u32, Ipv4Addr::from) >>
t: take!(6) >>
ip_target: map!(be_u32, Ipv4Addr::from) >>
(Box::new(ArpPacket {
hardware_type: hw_type,
protocol_type: p_type,
hardware_length: hw_len,
protocol_length: pr_len,
operation: oper,
sender_hardware_address: MacAddress(s[0], s[1], s[2], s[3], s[4], s[5]),
sender_protocol_address: ip_sender,
target_hardware_address: MacAddress(t[0], t[1], t[2], t[3], t[4], t[5]),
target_protocol_address: ip_target,
}))
)
}
}
impl fmt::Display for ArpParser {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ARP")
}
}
#[derive(Debug, Eq, PartialEq)]
pub struct ArpPacket {
pub hardware_type: ArpHardwareType,
pub protocol_type: EtherType,
pub hardware_length: u8,
pub protocol_length: u8,
pub operation: ArpOperation,
pub sender_hardware_address: MacAddress,
pub sender_protocol_address: Ipv4Addr,
pub target_hardware_address: MacAddress,
pub target_protocol_address: Ipv4Addr,
}
#[derive(Debug, Eq, PartialEq)]
pub enum ArpHardwareType {
Ethernet,
}
impl ArpHardwareType {
pub fn from_u16(input: u16) -> Option<ArpHardwareType> {
match input {
1 => Some(ArpHardwareType::Ethernet),
_ => None,
}
}
}
#[derive(Debug, Eq, PartialEq)]
pub enum ArpOperation {
Request,
Reply,
ReverseRequest,
ReverseReply,
}
impl ArpOperation {
pub fn from_u16(input: u16) -> Option<ArpOperation> {
match input {
1 => Some(ArpOperation::Request),
2 => Some(ArpOperation::Reply),
3 => Some(ArpOperation::ReverseRequest),
4 => Some(ArpOperation::ReverseReply),
_ => None,
}
}
}