Implement ARP snooping.
This commit is contained in:
parent
4421b2fe27
commit
7f1b88ef45
|
@ -8,8 +8,7 @@ fn main() {
|
|||
let ifname = env::args().nth(1).unwrap();
|
||||
let mut socket = RawSocket::new(ifname.as_ref()).unwrap();
|
||||
loop {
|
||||
socket.recv(|buffer| {
|
||||
print!("{}", PrettyPrinter::<EthernetFrame<_>>::new("", &buffer))
|
||||
})
|
||||
let buffer = socket.receive().unwrap();
|
||||
print!("{}", PrettyPrinter::<EthernetFrame<&[u8]>>::new("", &buffer))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,33 +2,10 @@
|
|||
extern crate smoltcp;
|
||||
|
||||
use std::env;
|
||||
use smoltcp::phy::{Device, TapInterface};
|
||||
use smoltcp::wire::{PrettyPrinter, EthernetFrame, EthernetAddress};
|
||||
use smoltcp::phy::{Tracer, TapInterface};
|
||||
use smoltcp::wire::{EthernetFrame, EthernetAddress};
|
||||
use smoltcp::iface::{ProtocolAddress, SliceArpCache, EthernetInterface};
|
||||
|
||||
struct TracingDevice<T: Device>(T);
|
||||
|
||||
impl<T: Device> Device for TracingDevice<T> {
|
||||
fn mtu(&self) -> usize {
|
||||
self.0.mtu()
|
||||
}
|
||||
|
||||
fn recv<R, F: FnOnce(&[u8]) -> R>(&self, handler: F) -> R {
|
||||
self.0.recv(|buffer| {
|
||||
print!("{}", PrettyPrinter::<EthernetFrame<_>>::new("<- ", &buffer));
|
||||
handler(buffer)
|
||||
})
|
||||
}
|
||||
|
||||
fn send<R, F: FnOnce(&mut [u8]) -> R>(&self, len: usize, handler: F) -> R {
|
||||
self.0.send(len, |buffer| {
|
||||
let result = handler(buffer);
|
||||
print!("{}", PrettyPrinter::<EthernetFrame<_>>::new("-> ", &buffer));
|
||||
result
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let ifname = env::args().nth(1).unwrap();
|
||||
|
||||
|
@ -36,7 +13,7 @@ fn main() {
|
|||
let protocol_addrs = [ProtocolAddress::ipv4([192, 168, 69, 1])];
|
||||
|
||||
let device = TapInterface::new(ifname.as_ref()).unwrap();
|
||||
let device = TracingDevice(device);
|
||||
let device = Tracer::<_, EthernetFrame<&[u8]>>::new(device);
|
||||
|
||||
let mut arp_cache_data = [Default::default(); 8];
|
||||
let arp_cache = SliceArpCache::new(&mut arp_cache_data);
|
||||
|
|
|
@ -75,57 +75,53 @@ impl<'a, DeviceT: Device, ArpCacheT: ArpCache> Interface<'a, DeviceT, ArpCacheT>
|
|||
Nop,
|
||||
Arp(ArpRepr)
|
||||
}
|
||||
let mut response = Response::Nop;
|
||||
|
||||
let response = try!(self.device.recv(|buffer| {
|
||||
let frame = try!(EthernetFrame::new(buffer));
|
||||
match frame.ethertype() {
|
||||
EthernetProtocolType::Arp => {
|
||||
let packet = try!(ArpPacket::new(frame.payload()));
|
||||
let repr = try!(ArpRepr::parse(&packet));
|
||||
match repr {
|
||||
ArpRepr::EthernetIpv4 {
|
||||
operation: ArpOperation::Request,
|
||||
source_hardware_addr, source_protocol_addr,
|
||||
target_protocol_addr, ..
|
||||
} => {
|
||||
if self.has_protocol_addr(target_protocol_addr) {
|
||||
Ok(Response::Arp(ArpRepr::EthernetIpv4 {
|
||||
operation: ArpOperation::Reply,
|
||||
source_hardware_addr: self.hardware_addr,
|
||||
source_protocol_addr: target_protocol_addr,
|
||||
target_hardware_addr: source_hardware_addr,
|
||||
target_protocol_addr: source_protocol_addr
|
||||
}))
|
||||
} else {
|
||||
Ok(Response::Nop)
|
||||
}
|
||||
},
|
||||
_ => Err(Error::Unrecognized)
|
||||
}
|
||||
},
|
||||
_ => Err(Error::Unrecognized)
|
||||
}
|
||||
}));
|
||||
|
||||
// TODO: accurately calculate the outgoing packet size?
|
||||
let size = self.device.mtu();
|
||||
let rx_buffer = try!(self.device.receive());
|
||||
let frame = try!(EthernetFrame::new(rx_buffer));
|
||||
match frame.ethertype() {
|
||||
EthernetProtocolType::Arp => {
|
||||
let packet = try!(ArpPacket::new(frame.payload()));
|
||||
let repr = try!(ArpRepr::parse(&packet));
|
||||
match repr {
|
||||
ArpRepr::EthernetIpv4 {
|
||||
operation: ArpOperation::Request,
|
||||
source_hardware_addr, source_protocol_addr,
|
||||
target_protocol_addr, ..
|
||||
} => {
|
||||
if self.has_protocol_addr(target_protocol_addr) {
|
||||
response = Response::Arp(ArpRepr::EthernetIpv4 {
|
||||
operation: ArpOperation::Reply,
|
||||
source_hardware_addr: self.hardware_addr,
|
||||
source_protocol_addr: target_protocol_addr,
|
||||
target_hardware_addr: source_hardware_addr,
|
||||
target_protocol_addr: source_protocol_addr
|
||||
})
|
||||
}
|
||||
},
|
||||
_ => return Err(Error::Unrecognized)
|
||||
}
|
||||
},
|
||||
_ => return Err(Error::Unrecognized)
|
||||
}
|
||||
|
||||
match response {
|
||||
Response::Nop => Ok(()),
|
||||
Response::Arp(repr) => {
|
||||
self.device.send(size, |buffer| {
|
||||
let mut frame = try!(EthernetFrame::new(buffer));
|
||||
frame.set_source(self.hardware_addr);
|
||||
frame.set_destination(match repr {
|
||||
ArpRepr::EthernetIpv4 { target_hardware_addr, .. } => target_hardware_addr,
|
||||
_ => unreachable!()
|
||||
});
|
||||
let tx_size = self.device.mtu();
|
||||
let tx_buffer = try!(self.device.transmit(tx_size));
|
||||
let mut frame = try!(EthernetFrame::new(tx_buffer));
|
||||
frame.set_source(self.hardware_addr);
|
||||
frame.set_destination(match repr {
|
||||
ArpRepr::EthernetIpv4 { target_hardware_addr, .. } => target_hardware_addr,
|
||||
_ => unreachable!()
|
||||
});
|
||||
frame.set_ethertype(EthernetProtocolType::Arp);
|
||||
|
||||
let mut packet = try!(ArpPacket::new(frame.payload_mut()));
|
||||
repr.emit(&mut packet);
|
||||
let mut packet = try!(ArpPacket::new(frame.payload_mut()));
|
||||
repr.emit(&mut packet);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,15 +4,20 @@
|
|||
//! for transmitting and receiving frames, [Device](trait.Device.html),
|
||||
//! as well as an implementations of that trait that uses the host OS,
|
||||
//! [RawSocket](struct.RawSocket.html) and [TapInterface](struct.TapInterface.html).
|
||||
use Error;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
mod sys;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
mod tracer;
|
||||
#[cfg(feature = "std")]
|
||||
mod raw_socket;
|
||||
#[cfg(all(feature = "std", target_os = "linux"))]
|
||||
mod tap_interface;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use self::tracer::Tracer;
|
||||
#[cfg(feature = "std")]
|
||||
pub use self::raw_socket::RawSocket;
|
||||
#[cfg(all(feature = "std", target_os = "linux"))]
|
||||
|
@ -24,29 +29,26 @@ pub use self::tap_interface::TapInterface;
|
|||
/// and receiving packets from memory pools; hence, the stack borrows the buffer for a packet
|
||||
/// that it is about to receive, as well for a packet that it is about to send, from the device.
|
||||
pub trait Device {
|
||||
/// Maximum transmission unit.
|
||||
type RxBuffer: AsRef<[u8]>;
|
||||
type TxBuffer: AsRef<[u8]> + AsMut<[u8]>;
|
||||
|
||||
/// Get maximum transmission unit.
|
||||
///
|
||||
/// The network device is unable to send or receive frames larger than the MTU.
|
||||
/// In practice, MTU will fall between 576 (for IPv4) or 1280 (for IPv6) and 9216 octets.
|
||||
fn mtu(&self) -> usize;
|
||||
|
||||
/// Receives a frame.
|
||||
/// Receive a frame.
|
||||
///
|
||||
/// It is expected that a `recv` implementation, once a packet is written to memory
|
||||
/// It is expected that a `receive` implementation, once a packet is written to memory
|
||||
/// through DMA, would gain ownership of the underlying buffer, provide it for parsing,
|
||||
/// and then return it to the network device.
|
||||
///
|
||||
/// # Panics
|
||||
/// This function may panic if called recursively.
|
||||
fn recv<R, F: FnOnce(&[u8]) -> R>(&self, handler: F) -> R;
|
||||
/// and return it to the network device once it is dropped.
|
||||
fn receive(&mut self) -> Result<Self::RxBuffer, Error>;
|
||||
|
||||
/// Transmits a frame.
|
||||
/// Transmit a frame.
|
||||
///
|
||||
/// It is expected that a `send` implementation would gain ownership of a buffer with
|
||||
/// the requested length, provide it for emission, and then schedule it to be read from
|
||||
/// memory by the network device.
|
||||
///
|
||||
/// # Panics
|
||||
/// This function may panic if `len` is larger than `MTU`, or if called recursively.
|
||||
fn send<R, F: FnOnce(&mut [u8]) -> R>(&self, len: usize, handler: F) -> R;
|
||||
/// It is expected that a `transmit` implementation would gain ownership of a buffer with
|
||||
/// the requested length, provide it for emission, and schedule it to be read from
|
||||
/// memory by the network device once it is dropped.
|
||||
fn transmit(&mut self, len: usize) -> Result<Self::TxBuffer, Error>;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
use std::cell::RefCell;
|
||||
use std::vec::Vec;
|
||||
use std::rc::Rc;
|
||||
use std::io;
|
||||
|
||||
use Error;
|
||||
use super::{sys, Device};
|
||||
|
||||
/// A socket that captures or transmits the complete frame.
|
||||
#[derive(Debug)]
|
||||
pub struct RawSocket {
|
||||
lower: RefCell<sys::RawSocketDesc>,
|
||||
buffer: RefCell<Vec<u8>>
|
||||
lower: Rc<RefCell<sys::RawSocketDesc>>,
|
||||
mtu: usize
|
||||
}
|
||||
|
||||
impl RawSocket {
|
||||
|
@ -18,34 +21,52 @@ impl RawSocket {
|
|||
pub fn new(name: &str) -> io::Result<RawSocket> {
|
||||
let mut lower = try!(sys::RawSocketDesc::new(name));
|
||||
try!(lower.bind_interface());
|
||||
|
||||
let mut buffer = Vec::new();
|
||||
buffer.resize(try!(lower.interface_mtu()), 0);
|
||||
let mtu = try!(lower.interface_mtu());
|
||||
Ok(RawSocket {
|
||||
lower: RefCell::new(lower),
|
||||
buffer: RefCell::new(buffer)
|
||||
lower: Rc::new(RefCell::new(lower)),
|
||||
mtu: mtu
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for RawSocket {
|
||||
fn mtu(&self) -> usize {
|
||||
type RxBuffer = Vec<u8>;
|
||||
type TxBuffer = TxBuffer;
|
||||
|
||||
fn mtu(&self) -> usize { self.mtu }
|
||||
|
||||
fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
|
||||
let mut lower = self.lower.borrow_mut();
|
||||
lower.interface_mtu().unwrap()
|
||||
let mut buffer = vec![0; self.mtu];
|
||||
lower.recv(&mut buffer[..]).unwrap();
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
fn recv<R, F: FnOnce(&[u8]) -> R>(&self, handler: F) -> R {
|
||||
let mut lower = self.lower.borrow_mut();
|
||||
let mut buffer = self.buffer.borrow_mut();
|
||||
let len = lower.recv(&mut buffer[..]).unwrap();
|
||||
handler(&buffer[..len])
|
||||
}
|
||||
|
||||
fn send<R, F: FnOnce(&mut [u8]) -> R>(&self, len: usize, handler: F) -> R {
|
||||
let mut lower = self.lower.borrow_mut();
|
||||
let mut buffer = self.buffer.borrow_mut();
|
||||
let result = handler(&mut buffer[..len]);
|
||||
lower.send(&buffer[..len]).unwrap();
|
||||
result
|
||||
fn transmit(&mut self, len: usize) -> Result<Self::TxBuffer, Error> {
|
||||
Ok(TxBuffer {
|
||||
lower: self.lower.clone(),
|
||||
buffer: vec![0; len]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct TxBuffer {
|
||||
lower: Rc<RefCell<sys::RawSocketDesc>>,
|
||||
buffer: Vec<u8>
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for TxBuffer {
|
||||
fn as_ref(&self) -> &[u8] { self.buffer.as_ref() }
|
||||
}
|
||||
|
||||
impl AsMut<[u8]> for TxBuffer {
|
||||
fn as_mut(&mut self) -> &mut [u8] { self.buffer.as_mut() }
|
||||
}
|
||||
|
||||
impl Drop for TxBuffer {
|
||||
fn drop(&mut self) {
|
||||
let mut lower = self.lower.borrow_mut();
|
||||
lower.send(&mut self.buffer[..]).unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
use std::cell::RefCell;
|
||||
use std::vec::Vec;
|
||||
use std::rc::Rc;
|
||||
use std::io;
|
||||
|
||||
use Error;
|
||||
use super::{sys, Device};
|
||||
|
||||
/// A virtual Ethernet interface.
|
||||
#[derive(Debug)]
|
||||
pub struct TapInterface {
|
||||
lower: RefCell<sys::TapInterfaceDesc>,
|
||||
buffer: RefCell<Vec<u8>>
|
||||
lower: Rc<RefCell<sys::TapInterfaceDesc>>,
|
||||
mtu: usize
|
||||
}
|
||||
|
||||
impl TapInterface {
|
||||
|
@ -19,34 +22,51 @@ impl TapInterface {
|
|||
pub fn new(name: &str) -> io::Result<TapInterface> {
|
||||
let mut lower = try!(sys::TapInterfaceDesc::new(name));
|
||||
try!(lower.attach_interface());
|
||||
|
||||
let mut buffer = Vec::new();
|
||||
buffer.resize(1536, 0);
|
||||
Ok(TapInterface {
|
||||
lower: RefCell::new(lower),
|
||||
buffer: RefCell::new(buffer)
|
||||
lower: Rc::new(RefCell::new(lower)),
|
||||
mtu: 1536 // FIXME: get the real value somehow
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for TapInterface {
|
||||
fn mtu(&self) -> usize {
|
||||
let buffer = self.buffer.borrow();
|
||||
buffer.len()
|
||||
type RxBuffer = Vec<u8>;
|
||||
type TxBuffer = TxBuffer;
|
||||
|
||||
fn mtu(&self) -> usize { self.mtu }
|
||||
|
||||
fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
|
||||
let mut lower = self.lower.borrow_mut();
|
||||
let mut buffer = vec![0; self.mtu];
|
||||
lower.recv(&mut buffer[..]).unwrap();
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
fn recv<R, F: FnOnce(&[u8]) -> R>(&self, handler: F) -> R {
|
||||
let mut lower = self.lower.borrow_mut();
|
||||
let mut buffer = self.buffer.borrow_mut();
|
||||
let len = lower.recv(&mut buffer[..]).unwrap();
|
||||
handler(&buffer[..len])
|
||||
}
|
||||
|
||||
fn send<R, F: FnOnce(&mut [u8]) -> R>(&self, len: usize, handler: F) -> R {
|
||||
let mut lower = self.lower.borrow_mut();
|
||||
let mut buffer = self.buffer.borrow_mut();
|
||||
let result = handler(&mut buffer[..len]);
|
||||
lower.send(&buffer[..len]).unwrap();
|
||||
result
|
||||
fn transmit(&mut self, len: usize) -> Result<Self::TxBuffer, Error> {
|
||||
Ok(TxBuffer {
|
||||
lower: self.lower.clone(),
|
||||
buffer: vec![0; len]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct TxBuffer {
|
||||
lower: Rc<RefCell<sys::TapInterfaceDesc>>,
|
||||
buffer: Vec<u8>
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for TxBuffer {
|
||||
fn as_ref(&self) -> &[u8] { self.buffer.as_ref() }
|
||||
}
|
||||
|
||||
impl AsMut<[u8]> for TxBuffer {
|
||||
fn as_mut(&mut self) -> &mut [u8] { self.buffer.as_mut() }
|
||||
}
|
||||
|
||||
impl Drop for TxBuffer {
|
||||
fn drop(&mut self) {
|
||||
let mut lower = self.lower.borrow_mut();
|
||||
lower.send(&mut self.buffer[..]).unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
use core::marker::PhantomData;
|
||||
|
||||
use Error;
|
||||
use wire::pretty_print::{PrettyPrint, PrettyPrinter};
|
||||
use super::Device;
|
||||
|
||||
/// A tracer device.
|
||||
///
|
||||
/// A tracer is a device that prints all packets traversing it
|
||||
/// to the standard output, and delegates to another device otherwise.
|
||||
pub struct Tracer<T: Device, U: PrettyPrint> {
|
||||
lower: T,
|
||||
phantom: PhantomData<U>
|
||||
}
|
||||
|
||||
impl<T: Device, U: PrettyPrint> Tracer<T, U> {
|
||||
/// Create a tracer device.
|
||||
pub fn new(lower: T) -> Tracer<T, U> {
|
||||
Tracer {
|
||||
lower: lower,
|
||||
phantom: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the underlying device, consuming the tracer.
|
||||
pub fn into_lower(self) -> T {
|
||||
self.lower
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Device, U: PrettyPrint> Device for Tracer<T, U> {
|
||||
type RxBuffer = T::RxBuffer;
|
||||
type TxBuffer = TxBuffer<T::TxBuffer, U>;
|
||||
|
||||
fn mtu(&self) -> usize { self.lower.mtu() }
|
||||
|
||||
fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
|
||||
let buffer = try!(self.lower.receive());
|
||||
print!("{}", PrettyPrinter::<U>::new("<- ", &buffer));
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
fn transmit(&mut self, len: usize) -> Result<Self::TxBuffer, Error> {
|
||||
let buffer = try!(self.lower.transmit(len));
|
||||
Ok(TxBuffer {
|
||||
buffer: buffer,
|
||||
phantom: PhantomData
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct TxBuffer<T: AsRef<[u8]>, U: PrettyPrint> {
|
||||
buffer: T,
|
||||
phantom: PhantomData<U>
|
||||
}
|
||||
|
||||
impl<T: AsRef<[u8]>, U: PrettyPrint> AsRef<[u8]>
|
||||
for TxBuffer<T, U> {
|
||||
fn as_ref(&self) -> &[u8] { self.buffer.as_ref() }
|
||||
}
|
||||
|
||||
impl<T: AsRef<[u8]> + AsMut<[u8]>, U: PrettyPrint> AsMut<[u8]>
|
||||
for TxBuffer<T, U> {
|
||||
fn as_mut(&mut self) -> &mut [u8] { self.buffer.as_mut() }
|
||||
}
|
||||
|
||||
impl<T: AsRef<[u8]>, U: PrettyPrint> Drop for TxBuffer<T, U> {
|
||||
fn drop(&mut self) {
|
||||
print!("{}", PrettyPrinter::<U>::new("-> ", &self.buffer));
|
||||
}
|
||||
}
|
|
@ -314,8 +314,8 @@ impl fmt::Display for Repr {
|
|||
|
||||
use super::pretty_print::{PrettyPrint, PrettyIndent};
|
||||
|
||||
impl<T: AsRef<[u8]>> PrettyPrint<T> for Packet<T> {
|
||||
fn pretty_print(buffer: T, f: &mut fmt::Formatter,
|
||||
impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
|
||||
fn pretty_print(buffer: &AsRef<[u8]>, f: &mut fmt::Formatter,
|
||||
indent: &mut PrettyIndent) -> fmt::Result {
|
||||
match Packet::new(buffer) {
|
||||
Err(err) => write!(f, "{}({})\n", indent, err),
|
||||
|
|
|
@ -164,8 +164,8 @@ impl<T: AsRef<[u8]>> fmt::Display for Frame<T> {
|
|||
|
||||
use super::pretty_print::{PrettyPrint, PrettyIndent};
|
||||
|
||||
impl<T: AsRef<[u8]>> PrettyPrint<T> for Frame<T> {
|
||||
fn pretty_print(buffer: T, f: &mut fmt::Formatter,
|
||||
impl<T: AsRef<[u8]>> PrettyPrint for Frame<T> {
|
||||
fn pretty_print(buffer: &AsRef<[u8]>, f: &mut fmt::Formatter,
|
||||
indent: &mut PrettyIndent) -> fmt::Result {
|
||||
let frame = match Frame::new(buffer) {
|
||||
Err(err) => return write!(f, "{}({})\n", indent, err),
|
||||
|
@ -176,7 +176,7 @@ impl<T: AsRef<[u8]>> PrettyPrint<T> for Frame<T> {
|
|||
|
||||
match frame.ethertype() {
|
||||
EtherType::Arp =>
|
||||
super::ArpPacket::pretty_print(frame.payload(), f, indent),
|
||||
super::ArpPacket::<&[u8]>::pretty_print(&frame.payload(), f, indent),
|
||||
_ => Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -210,8 +210,8 @@ mod test {
|
|||
#[test]
|
||||
fn test_deconstruct() {
|
||||
let frame = Frame::new(&FRAME_BYTES[..]).unwrap();
|
||||
assert_eq!(frame.source(), Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]));
|
||||
assert_eq!(frame.destination(), Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16]));
|
||||
assert_eq!(frame.destination(), Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]));
|
||||
assert_eq!(frame.source(), Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16]));
|
||||
assert_eq!(frame.ethertype(), EtherType::Ipv4);
|
||||
assert_eq!(frame.payload(), &PAYLOAD_BYTES[..]);
|
||||
}
|
||||
|
@ -220,8 +220,8 @@ mod test {
|
|||
fn test_construct() {
|
||||
let mut bytes = vec![0; 64];
|
||||
let mut frame = Frame::new(&mut bytes).unwrap();
|
||||
frame.set_source(Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]));
|
||||
frame.set_destination(Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16]));
|
||||
frame.set_destination(Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]));
|
||||
frame.set_source(Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16]));
|
||||
frame.set_ethertype(EtherType::Ipv4);
|
||||
frame.payload_mut().copy_from_slice(&PAYLOAD_BYTES[..]);
|
||||
assert_eq!(&frame.into_inner()[..], &FRAME_BYTES[..]);
|
||||
|
|
|
@ -45,23 +45,24 @@ impl fmt::Display for PrettyIndent {
|
|||
}
|
||||
|
||||
/// Interface for printing listings.
|
||||
pub trait PrettyPrint<T: AsRef<[u8]>> {
|
||||
pub trait PrettyPrint {
|
||||
/// Write a concise, formatted representation of a packet contained in the provided
|
||||
/// buffer, and any nested packets it may contain.
|
||||
///
|
||||
/// `pretty_print` accepts a buffer and not a packet wrapper because the packet might
|
||||
/// be truncated, and so it might not be possible to create the packet wrapper.
|
||||
fn pretty_print(buffer: T, fmt: &mut fmt::Formatter, indent: &mut PrettyIndent) -> fmt::Result;
|
||||
fn pretty_print(buffer: &AsRef<[u8]>, fmt: &mut fmt::Formatter,
|
||||
indent: &mut PrettyIndent) -> fmt::Result;
|
||||
}
|
||||
|
||||
/// Wrapper for using a `PrettyPrint` where a `Display` is expected.
|
||||
pub struct PrettyPrinter<'a, T: PrettyPrint<&'a AsRef<[u8]>>> {
|
||||
pub struct PrettyPrinter<'a, T: PrettyPrint> {
|
||||
prefix: &'static str,
|
||||
buffer: &'a AsRef<[u8]>,
|
||||
phantom: PhantomData<T>
|
||||
}
|
||||
|
||||
impl<'a, T: PrettyPrint<&'a AsRef<[u8]>>> PrettyPrinter<'a, T> {
|
||||
impl<'a, T: PrettyPrint> PrettyPrinter<'a, T> {
|
||||
/// Format the listing with the recorded parameters when Display::fmt is called.
|
||||
pub fn new(prefix: &'static str, buffer: &'a AsRef<[u8]>) -> PrettyPrinter<'a, T> {
|
||||
PrettyPrinter {
|
||||
|
@ -72,8 +73,8 @@ impl<'a, T: PrettyPrint<&'a AsRef<[u8]>>> PrettyPrinter<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: PrettyPrint<&'a AsRef<[u8]>>> fmt::Display for PrettyPrinter<'a, T> {
|
||||
impl<'a, T: PrettyPrint> fmt::Display for PrettyPrinter<'a, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
T::pretty_print(self.buffer, f, &mut PrettyIndent::new(self.prefix))
|
||||
T::pretty_print(&self.buffer, f, &mut PrettyIndent::new(self.prefix))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue