2017-09-02 03:31:09 +08:00
|
|
|
// Heads up! Before working on this file you should read the parts
|
|
|
|
// of RFC 1122 that discuss Ethernet, ARP and IP.
|
|
|
|
|
2017-01-10 19:37:12 +08:00
|
|
|
use managed::{Managed, ManagedSlice};
|
2016-12-15 13:15:00 +08:00
|
|
|
|
2017-07-27 21:51:02 +08:00
|
|
|
use {Error, Result};
|
2016-12-12 10:39:46 +08:00
|
|
|
use phy::Device;
|
2016-12-20 21:54:11 +08:00
|
|
|
use wire::{EthernetAddress, EthernetProtocol, EthernetFrame};
|
2016-12-12 15:19:53 +08:00
|
|
|
use wire::{ArpPacket, ArpRepr, ArpOperation};
|
2016-12-26 19:20:20 +08:00
|
|
|
use wire::{Ipv4Packet, Ipv4Repr};
|
2016-12-21 03:18:35 +08:00
|
|
|
use wire::{Icmpv4Packet, Icmpv4Repr, Icmpv4DstUnreachable};
|
2016-12-26 19:20:20 +08:00
|
|
|
use wire::{IpAddress, IpProtocol, IpRepr};
|
2017-08-28 11:50:40 +08:00
|
|
|
use wire::{UdpPacket, UdpRepr, TcpPacket, TcpRepr, TcpControl};
|
|
|
|
use socket::{Socket, SocketSet, RawSocket, TcpSocket, UdpSocket, AsSocket};
|
2017-01-11 13:25:54 +08:00
|
|
|
use super::ArpCache;
|
2016-12-12 10:39:46 +08:00
|
|
|
|
|
|
|
/// An Ethernet network interface.
|
2016-12-15 13:15:00 +08:00
|
|
|
///
|
|
|
|
/// The network interface logically owns a number of other data structures; to avoid
|
|
|
|
/// a dependency on heap allocation, it instead owns a `BorrowMut<[T]>`, which can be
|
|
|
|
/// a `&mut [T]`, or `Vec<T>` if a heap is available.
|
2017-01-11 13:25:54 +08:00
|
|
|
pub struct Interface<'a, 'b, 'c, DeviceT: Device + 'a> {
|
2017-01-10 19:37:12 +08:00
|
|
|
device: Managed<'a, DeviceT>,
|
2017-01-11 13:25:54 +08:00
|
|
|
arp_cache: Managed<'b, ArpCache>,
|
2016-12-12 15:19:53 +08:00
|
|
|
hardware_addr: EthernetAddress,
|
2017-01-11 13:25:54 +08:00
|
|
|
protocol_addrs: ManagedSlice<'c, IpAddress>,
|
2016-12-12 10:39:46 +08:00
|
|
|
}
|
|
|
|
|
2017-08-30 03:35:09 +08:00
|
|
|
enum Packet<'a> {
|
|
|
|
None,
|
2017-06-26 00:08:32 +08:00
|
|
|
Arp(ArpRepr),
|
|
|
|
Icmpv4(Ipv4Repr, Icmpv4Repr<'a>),
|
2017-08-28 11:50:40 +08:00
|
|
|
Raw((IpRepr, &'a [u8])),
|
|
|
|
Udp((IpRepr, UdpRepr<'a>)),
|
|
|
|
Tcp((IpRepr, TcpRepr<'a>))
|
2017-06-26 00:08:32 +08:00
|
|
|
}
|
|
|
|
|
2017-01-11 13:25:54 +08:00
|
|
|
impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
|
2016-12-12 10:39:46 +08:00
|
|
|
/// Create a network interface using the provided network device.
|
|
|
|
///
|
2016-12-15 13:15:00 +08:00
|
|
|
/// # Panics
|
|
|
|
/// See the restrictions on [set_hardware_addr](#method.set_hardware_addr)
|
|
|
|
/// and [set_protocol_addrs](#method.set_protocol_addrs) functions.
|
2017-01-11 13:25:54 +08:00
|
|
|
pub fn new<DeviceMT, ArpCacheMT, ProtocolAddrsMT>
|
|
|
|
(device: DeviceMT, arp_cache: ArpCacheMT,
|
|
|
|
hardware_addr: EthernetAddress, protocol_addrs: ProtocolAddrsMT) ->
|
|
|
|
Interface<'a, 'b, 'c, DeviceT>
|
2017-01-10 19:37:12 +08:00
|
|
|
where DeviceMT: Into<Managed<'a, DeviceT>>,
|
2017-01-11 13:25:54 +08:00
|
|
|
ArpCacheMT: Into<Managed<'b, ArpCache>>,
|
|
|
|
ProtocolAddrsMT: Into<ManagedSlice<'c, IpAddress>>, {
|
2017-01-10 19:37:12 +08:00
|
|
|
let device = device.into();
|
|
|
|
let arp_cache = arp_cache.into();
|
2017-01-11 13:25:54 +08:00
|
|
|
let protocol_addrs = protocol_addrs.into();
|
2017-01-10 19:37:12 +08:00
|
|
|
|
2016-12-15 13:15:00 +08:00
|
|
|
Self::check_hardware_addr(&hardware_addr);
|
2017-01-10 19:37:12 +08:00
|
|
|
Self::check_protocol_addrs(&protocol_addrs);
|
2016-12-12 10:39:46 +08:00
|
|
|
Interface {
|
2016-12-12 15:19:53 +08:00
|
|
|
device: device,
|
|
|
|
arp_cache: arp_cache,
|
2016-12-15 13:15:00 +08:00
|
|
|
hardware_addr: hardware_addr,
|
|
|
|
protocol_addrs: protocol_addrs,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check_hardware_addr(addr: &EthernetAddress) {
|
|
|
|
if addr.is_multicast() {
|
|
|
|
panic!("hardware address {} is not unicast", addr)
|
2016-12-12 10:39:46 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get the hardware address of the interface.
|
|
|
|
pub fn hardware_addr(&self) -> EthernetAddress {
|
|
|
|
self.hardware_addr
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set the hardware address of the interface.
|
|
|
|
///
|
|
|
|
/// # Panics
|
2016-12-12 15:19:53 +08:00
|
|
|
/// This function panics if the address is not unicast.
|
2016-12-12 10:39:46 +08:00
|
|
|
pub fn set_hardware_addr(&mut self, addr: EthernetAddress) {
|
2016-12-15 13:15:00 +08:00
|
|
|
self.hardware_addr = addr;
|
|
|
|
Self::check_hardware_addr(&self.hardware_addr);
|
|
|
|
}
|
2016-12-12 15:19:53 +08:00
|
|
|
|
2016-12-20 21:54:11 +08:00
|
|
|
fn check_protocol_addrs(addrs: &[IpAddress]) {
|
2016-12-15 13:15:00 +08:00
|
|
|
for addr in addrs {
|
|
|
|
if !addr.is_unicast() {
|
|
|
|
panic!("protocol address {} is not unicast", addr)
|
|
|
|
}
|
|
|
|
}
|
2016-12-12 10:39:46 +08:00
|
|
|
}
|
2016-12-12 15:19:53 +08:00
|
|
|
|
|
|
|
/// Get the protocol addresses of the interface.
|
2016-12-20 21:54:11 +08:00
|
|
|
pub fn protocol_addrs(&self) -> &[IpAddress] {
|
2017-01-10 19:37:12 +08:00
|
|
|
self.protocol_addrs.as_ref()
|
2016-12-12 15:19:53 +08:00
|
|
|
}
|
|
|
|
|
2016-12-15 13:15:00 +08:00
|
|
|
/// Update the protocol addresses of the interface.
|
2016-12-12 15:19:53 +08:00
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
/// This function panics if any of the addresses is not unicast.
|
2017-01-11 13:25:54 +08:00
|
|
|
pub fn update_protocol_addrs<F: FnOnce(&mut ManagedSlice<'c, IpAddress>)>(&mut self, f: F) {
|
2016-12-21 06:57:21 +08:00
|
|
|
f(&mut self.protocol_addrs);
|
2017-01-10 19:37:12 +08:00
|
|
|
Self::check_protocol_addrs(&self.protocol_addrs)
|
2016-12-12 15:19:53 +08:00
|
|
|
}
|
|
|
|
|
2016-12-17 12:15:12 +08:00
|
|
|
/// Check whether the interface has the given protocol address assigned.
|
2016-12-20 21:54:11 +08:00
|
|
|
pub fn has_protocol_addr<T: Into<IpAddress>>(&self, addr: T) -> bool {
|
2016-12-12 15:19:53 +08:00
|
|
|
let addr = addr.into();
|
2017-01-10 19:37:12 +08:00
|
|
|
self.protocol_addrs.iter().any(|&probe| probe == addr)
|
2016-12-12 15:19:53 +08:00
|
|
|
}
|
|
|
|
|
2017-08-30 03:35:09 +08:00
|
|
|
/// Transmit packets queued in the given sockets, and receive packets queued
|
|
|
|
/// in the device.
|
2016-12-31 16:35:07 +08:00
|
|
|
///
|
2017-08-30 03:35:09 +08:00
|
|
|
/// The timestamp must be a number of milliseconds, monotonically increasing
|
|
|
|
/// since an arbitrary moment in time, such as system startup.
|
|
|
|
///
|
|
|
|
/// This function returns a _soft deadline_ for calling it the next time.
|
|
|
|
/// That is, if `iface.poll(&mut sockets, 1000)` returns `Ok(Some(2000))`,
|
|
|
|
/// it harmless (but wastes energy) to call it 500 ms later, and potentially
|
|
|
|
/// harmful (impacting quality of service) to call it 1500 ms later.
|
|
|
|
pub fn poll(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<Option<u64>> {
|
|
|
|
self.socket_egress(sockets, timestamp)?;
|
|
|
|
|
|
|
|
if self.socket_ingress(sockets, timestamp)? {
|
|
|
|
Ok(Some(0))
|
|
|
|
} else {
|
|
|
|
Ok(sockets.iter().filter_map(|socket| socket.poll_at()).min())
|
2016-12-20 08:07:02 +08:00
|
|
|
}
|
2017-08-28 13:49:56 +08:00
|
|
|
}
|
|
|
|
|
2017-08-30 03:35:09 +08:00
|
|
|
fn socket_ingress(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<bool> {
|
|
|
|
let mut processed_any = false;
|
2017-08-28 13:49:56 +08:00
|
|
|
loop {
|
2017-08-30 03:35:09 +08:00
|
|
|
let frame =
|
|
|
|
match self.device.receive(timestamp) {
|
|
|
|
Ok(frame) => frame,
|
|
|
|
Err(Error::Exhausted) => break, // nothing to receive
|
|
|
|
Err(err) => return Err(err)
|
|
|
|
};
|
|
|
|
|
|
|
|
let response =
|
|
|
|
match self.process_ethernet(sockets, timestamp, &frame) {
|
|
|
|
Ok(response) => response,
|
|
|
|
Err(err) => {
|
|
|
|
net_debug!("cannot process ingress packet: {}", err);
|
2017-08-30 18:20:11 +08:00
|
|
|
return Err(err)
|
2017-08-30 03:35:09 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
processed_any = true;
|
|
|
|
|
|
|
|
match self.dispatch(timestamp, response) {
|
|
|
|
Ok(()) => (),
|
|
|
|
Err(err) => {
|
|
|
|
net_debug!("cannot dispatch response packet: {}", err);
|
2017-08-30 18:20:11 +08:00
|
|
|
return Err(err)
|
2017-08-30 03:35:09 +08:00
|
|
|
}
|
|
|
|
}
|
2017-08-28 13:49:56 +08:00
|
|
|
}
|
2017-08-30 03:35:09 +08:00
|
|
|
Ok(processed_any)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn socket_egress(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<()> {
|
|
|
|
let mut limits = self.device.limits();
|
|
|
|
limits.max_transmission_unit -= EthernetFrame::<&[u8]>::header_len();
|
|
|
|
|
2017-09-23 02:09:18 +08:00
|
|
|
for socket in sockets.iter_mut() {
|
|
|
|
let mut device_result = Ok(());
|
|
|
|
let socket_result =
|
|
|
|
match socket {
|
|
|
|
&mut Socket::Raw(ref mut socket) =>
|
|
|
|
socket.dispatch(|response| {
|
|
|
|
device_result = self.dispatch(timestamp, Packet::Raw(response));
|
|
|
|
device_result
|
|
|
|
}),
|
|
|
|
&mut Socket::Udp(ref mut socket) =>
|
|
|
|
socket.dispatch(|response| {
|
|
|
|
device_result = self.dispatch(timestamp, Packet::Udp(response));
|
|
|
|
device_result
|
|
|
|
}),
|
|
|
|
&mut Socket::Tcp(ref mut socket) =>
|
|
|
|
socket.dispatch(timestamp, &limits, |response| {
|
|
|
|
device_result = self.dispatch(timestamp, Packet::Tcp(response));
|
|
|
|
device_result
|
|
|
|
}),
|
|
|
|
&mut Socket::__Nonexhaustive => unreachable!()
|
|
|
|
};
|
|
|
|
match (device_result, socket_result) {
|
|
|
|
(Err(Error::Unaddressable), _) => break, // no one to transmit to
|
|
|
|
(Err(Error::Exhausted), _) => break, // nowhere to transmit
|
|
|
|
(Ok(()), Err(Error::Exhausted)) => (), // nothing to transmit
|
|
|
|
(Err(err), _) | (_, Err(err)) => {
|
|
|
|
net_debug!("cannot dispatch egress packet: {}", err);
|
|
|
|
return Err(err)
|
2017-08-30 18:20:11 +08:00
|
|
|
}
|
2017-09-23 02:09:18 +08:00
|
|
|
(Ok(()), Ok(())) => ()
|
2017-08-30 03:35:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
2017-08-28 13:49:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn process_ethernet<'frame, T: AsRef<[u8]>>
|
|
|
|
(&mut self, sockets: &mut SocketSet, timestamp: u64,
|
|
|
|
frame: &'frame T) ->
|
2017-08-30 03:35:09 +08:00
|
|
|
Result<Packet<'frame>> {
|
2017-08-28 13:49:56 +08:00
|
|
|
let eth_frame = EthernetFrame::new_checked(frame)?;
|
2016-12-13 23:18:56 +08:00
|
|
|
|
2017-06-26 00:08:32 +08:00
|
|
|
// Ignore any packets not directed to our hardware address.
|
2017-03-06 12:00:13 +08:00
|
|
|
if !eth_frame.dst_addr().is_broadcast() &&
|
|
|
|
eth_frame.dst_addr() != self.hardware_addr {
|
2017-08-30 03:35:09 +08:00
|
|
|
return Ok(Packet::None)
|
2017-03-06 12:00:13 +08:00
|
|
|
}
|
2017-03-06 11:58:19 +08:00
|
|
|
|
2017-08-28 13:49:56 +08:00
|
|
|
match eth_frame.ethertype() {
|
2017-06-26 00:08:32 +08:00
|
|
|
EthernetProtocol::Arp =>
|
2017-08-28 13:49:56 +08:00
|
|
|
self.process_arp(ð_frame),
|
2017-06-26 00:08:32 +08:00
|
|
|
EthernetProtocol::Ipv4 =>
|
2017-08-28 13:49:56 +08:00
|
|
|
self.process_ipv4(sockets, timestamp, ð_frame),
|
2017-06-26 00:08:32 +08:00
|
|
|
// Drop all other traffic.
|
2017-08-28 13:49:56 +08:00
|
|
|
_ => Err(Error::Unrecognized),
|
|
|
|
}
|
2017-06-26 00:08:32 +08:00
|
|
|
}
|
2016-12-23 15:31:02 +08:00
|
|
|
|
2017-06-26 00:08:32 +08:00
|
|
|
fn process_arp<'frame, T: AsRef<[u8]>>
|
|
|
|
(&mut self, eth_frame: &EthernetFrame<&'frame T>) ->
|
2017-08-30 03:35:09 +08:00
|
|
|
Result<Packet<'frame>> {
|
2017-06-26 00:08:32 +08:00
|
|
|
let arp_packet = ArpPacket::new_checked(eth_frame.payload())?;
|
|
|
|
let arp_repr = ArpRepr::parse(&arp_packet)?;
|
|
|
|
|
|
|
|
match arp_repr {
|
2017-08-21 15:08:06 +08:00
|
|
|
// Respond to ARP requests aimed at us, and fill the ARP cache from all ARP
|
|
|
|
// requests and replies, to minimize the chance that we have to perform
|
|
|
|
// an explicit ARP request.
|
2017-06-26 00:08:32 +08:00
|
|
|
ArpRepr::EthernetIpv4 {
|
2017-08-21 15:08:06 +08:00
|
|
|
operation, source_hardware_addr, source_protocol_addr, target_protocol_addr, ..
|
2017-06-26 00:08:32 +08:00
|
|
|
} => {
|
|
|
|
if source_protocol_addr.is_unicast() && source_hardware_addr.is_unicast() {
|
|
|
|
self.arp_cache.fill(&source_protocol_addr.into(),
|
|
|
|
&source_hardware_addr);
|
2017-08-21 15:08:06 +08:00
|
|
|
} else {
|
|
|
|
// Discard packets with non-unicast source addresses.
|
|
|
|
net_debug!("non-unicast source in {}", arp_repr);
|
|
|
|
return Err(Error::Malformed)
|
2017-03-07 14:32:09 +08:00
|
|
|
}
|
2016-12-23 15:31:02 +08:00
|
|
|
|
2017-08-22 15:44:43 +08:00
|
|
|
if operation == ArpOperation::Request &&
|
2017-08-21 15:08:06 +08:00
|
|
|
self.has_protocol_addr(target_protocol_addr) {
|
2017-08-30 03:35:09 +08:00
|
|
|
Ok(Packet::Arp(ArpRepr::EthernetIpv4 {
|
2017-06-26 00:08:32 +08:00
|
|
|
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 {
|
2017-08-30 03:35:09 +08:00
|
|
|
Ok(Packet::None)
|
2017-06-18 18:14:20 +08:00
|
|
|
}
|
2017-06-26 00:08:32 +08:00
|
|
|
}
|
2017-06-18 18:14:20 +08:00
|
|
|
|
2017-06-26 00:08:32 +08:00
|
|
|
_ => Err(Error::Unrecognized)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn process_ipv4<'frame, T: AsRef<[u8]>>
|
|
|
|
(&mut self, sockets: &mut SocketSet, timestamp: u64,
|
|
|
|
eth_frame: &EthernetFrame<&'frame T>) ->
|
2017-08-30 03:35:09 +08:00
|
|
|
Result<Packet<'frame>> {
|
2017-06-26 00:08:32 +08:00
|
|
|
let ipv4_packet = Ipv4Packet::new_checked(eth_frame.payload())?;
|
|
|
|
let ipv4_repr = Ipv4Repr::parse(&ipv4_packet)?;
|
|
|
|
|
2017-06-28 05:51:56 +08:00
|
|
|
if !ipv4_repr.src_addr.is_unicast() {
|
2017-06-27 01:01:23 +08:00
|
|
|
// Discard packets with non-unicast source addresses.
|
2017-08-21 15:08:06 +08:00
|
|
|
net_debug!("non-unicast source in {}", ipv4_repr);
|
2017-06-27 01:01:23 +08:00
|
|
|
return Err(Error::Malformed)
|
|
|
|
}
|
|
|
|
|
|
|
|
if eth_frame.src_addr().is_unicast() {
|
2017-06-26 00:08:32 +08:00
|
|
|
// Fill the ARP cache from IP header of unicast frames.
|
|
|
|
self.arp_cache.fill(&IpAddress::Ipv4(ipv4_repr.src_addr),
|
|
|
|
ð_frame.src_addr());
|
|
|
|
}
|
|
|
|
|
2017-08-28 12:50:57 +08:00
|
|
|
let ip_repr = IpRepr::Ipv4(ipv4_repr);
|
|
|
|
let ip_payload = ipv4_packet.payload();
|
|
|
|
|
2017-06-26 00:08:32 +08:00
|
|
|
// Pass every IP packet to all raw sockets we have registered.
|
|
|
|
let mut handled_by_raw_socket = false;
|
|
|
|
for raw_socket in sockets.iter_mut().filter_map(
|
|
|
|
<Socket as AsSocket<RawSocket>>::try_as_socket) {
|
2017-09-01 05:43:22 +08:00
|
|
|
if !raw_socket.accepts(&ip_repr) { continue }
|
|
|
|
|
2017-08-28 12:50:57 +08:00
|
|
|
match raw_socket.process(&ip_repr, ip_payload) {
|
2017-07-24 15:01:35 +08:00
|
|
|
// The packet is valid and handled by socket.
|
2017-06-26 00:08:32 +08:00
|
|
|
Ok(()) => handled_by_raw_socket = true,
|
2017-09-01 05:43:22 +08:00
|
|
|
// The socket buffer is full.
|
|
|
|
Err(Error::Exhausted) => (),
|
|
|
|
// Raw sockets don't validate the packets in any way.
|
|
|
|
Err(_) => unreachable!(),
|
2017-06-26 00:08:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !self.has_protocol_addr(ipv4_repr.dst_addr) {
|
|
|
|
// Ignore IP packets not directed at us.
|
2017-08-30 03:35:09 +08:00
|
|
|
return Ok(Packet::None)
|
2016-12-12 20:30:35 +08:00
|
|
|
}
|
2016-12-12 15:19:53 +08:00
|
|
|
|
2017-06-26 00:08:32 +08:00
|
|
|
match ipv4_repr.protocol {
|
|
|
|
IpProtocol::Icmp =>
|
2017-08-28 12:50:57 +08:00
|
|
|
Self::process_icmpv4(ipv4_repr, ip_payload),
|
2017-06-26 00:08:32 +08:00
|
|
|
IpProtocol::Udp =>
|
2017-08-28 18:36:27 +08:00
|
|
|
Self::process_udp(sockets, ip_repr, ip_payload),
|
2017-08-23 06:32:05 +08:00
|
|
|
IpProtocol::Tcp =>
|
2017-08-28 12:50:57 +08:00
|
|
|
Self::process_tcp(sockets, timestamp, ip_repr, ip_payload),
|
2017-07-24 14:56:06 +08:00
|
|
|
_ if handled_by_raw_socket =>
|
2017-08-30 03:35:09 +08:00
|
|
|
Ok(Packet::None),
|
2017-06-26 00:08:32 +08:00
|
|
|
_ => {
|
2017-07-24 14:56:06 +08:00
|
|
|
let icmp_reply_repr = Icmpv4Repr::DstUnreachable {
|
2017-07-24 15:07:43 +08:00
|
|
|
reason: Icmpv4DstUnreachable::ProtoUnreachable,
|
2017-07-24 14:56:06 +08:00
|
|
|
header: ipv4_repr,
|
2017-08-28 12:50:57 +08:00
|
|
|
data: &ip_payload[0..8]
|
2017-07-24 14:56:06 +08:00
|
|
|
};
|
|
|
|
let ipv4_reply_repr = Ipv4Repr {
|
|
|
|
src_addr: ipv4_repr.dst_addr,
|
|
|
|
dst_addr: ipv4_repr.src_addr,
|
|
|
|
protocol: IpProtocol::Icmp,
|
|
|
|
payload_len: icmp_reply_repr.buffer_len()
|
|
|
|
};
|
2017-08-30 03:35:09 +08:00
|
|
|
Ok(Packet::Icmpv4(ipv4_reply_repr, icmp_reply_repr))
|
2017-06-26 00:08:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn process_icmpv4<'frame>(ipv4_repr: Ipv4Repr, ip_payload: &'frame [u8]) ->
|
2017-08-30 03:35:09 +08:00
|
|
|
Result<Packet<'frame>> {
|
2017-06-26 00:08:32 +08:00
|
|
|
let icmp_packet = Icmpv4Packet::new_checked(ip_payload)?;
|
|
|
|
let icmp_repr = Icmpv4Repr::parse(&icmp_packet)?;
|
|
|
|
|
|
|
|
match icmp_repr {
|
|
|
|
// Respond to echo requests.
|
2017-08-28 12:50:57 +08:00
|
|
|
Icmpv4Repr::EchoRequest { ident, seq_no, data } => {
|
2017-06-26 00:08:32 +08:00
|
|
|
let icmp_reply_repr = Icmpv4Repr::EchoReply {
|
|
|
|
ident: ident,
|
|
|
|
seq_no: seq_no,
|
|
|
|
data: data
|
|
|
|
};
|
|
|
|
let ipv4_reply_repr = Ipv4Repr {
|
|
|
|
src_addr: ipv4_repr.dst_addr,
|
|
|
|
dst_addr: ipv4_repr.src_addr,
|
|
|
|
protocol: IpProtocol::Icmp,
|
|
|
|
payload_len: icmp_reply_repr.buffer_len()
|
|
|
|
};
|
2017-08-30 03:35:09 +08:00
|
|
|
Ok(Packet::Icmpv4(ipv4_reply_repr, icmp_reply_repr))
|
2017-06-26 00:08:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Ignore any echo replies.
|
2017-08-30 03:35:09 +08:00
|
|
|
Icmpv4Repr::EchoReply { .. } => Ok(Packet::None),
|
2017-06-26 00:08:32 +08:00
|
|
|
|
|
|
|
// FIXME: do something correct here?
|
|
|
|
_ => Err(Error::Unrecognized),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-28 18:36:27 +08:00
|
|
|
fn process_udp<'frame>(sockets: &mut SocketSet,
|
|
|
|
ip_repr: IpRepr, ip_payload: &'frame [u8]) ->
|
2017-08-30 03:35:09 +08:00
|
|
|
Result<Packet<'frame>> {
|
2017-08-28 12:50:57 +08:00
|
|
|
let (src_addr, dst_addr) = (ip_repr.src_addr(), ip_repr.dst_addr());
|
|
|
|
let udp_packet = UdpPacket::new_checked(ip_payload)?;
|
|
|
|
let udp_repr = UdpRepr::parse(&udp_packet, &src_addr, &dst_addr)?;
|
2017-07-24 14:56:06 +08:00
|
|
|
|
|
|
|
for udp_socket in sockets.iter_mut().filter_map(
|
|
|
|
<Socket as AsSocket<UdpSocket>>::try_as_socket) {
|
2017-09-01 05:44:21 +08:00
|
|
|
if !udp_socket.accepts(&ip_repr, &udp_repr) { continue }
|
|
|
|
|
2017-08-28 12:50:57 +08:00
|
|
|
match udp_socket.process(&ip_repr, &udp_repr) {
|
2017-07-24 15:01:35 +08:00
|
|
|
// The packet is valid and handled by socket.
|
2017-08-30 03:35:09 +08:00
|
|
|
Ok(()) => return Ok(Packet::None),
|
2017-09-01 05:44:21 +08:00
|
|
|
// The packet is malformed, or the socket buffer is full.
|
2017-07-24 14:56:06 +08:00
|
|
|
Err(e) => return Err(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-24 15:01:35 +08:00
|
|
|
// The packet wasn't handled by a socket, send an ICMP port unreachable packet.
|
2017-08-28 12:50:57 +08:00
|
|
|
match ip_repr {
|
|
|
|
IpRepr::Ipv4(ipv4_repr) => {
|
|
|
|
let icmpv4_reply_repr = Icmpv4Repr::DstUnreachable {
|
|
|
|
reason: Icmpv4DstUnreachable::PortUnreachable,
|
|
|
|
header: ipv4_repr,
|
|
|
|
data: &ip_payload[0..8]
|
|
|
|
};
|
|
|
|
let ipv4_reply_repr = Ipv4Repr {
|
|
|
|
src_addr: ipv4_repr.dst_addr,
|
|
|
|
dst_addr: ipv4_repr.src_addr,
|
|
|
|
protocol: IpProtocol::Icmp,
|
|
|
|
payload_len: icmpv4_reply_repr.buffer_len()
|
|
|
|
};
|
2017-08-30 03:35:09 +08:00
|
|
|
Ok(Packet::Icmpv4(ipv4_reply_repr, icmpv4_reply_repr))
|
2017-08-28 12:50:57 +08:00
|
|
|
},
|
|
|
|
IpRepr::Unspecified { .. } |
|
|
|
|
IpRepr::__Nonexhaustive =>
|
|
|
|
unreachable!()
|
|
|
|
}
|
2017-07-24 14:56:06 +08:00
|
|
|
}
|
|
|
|
|
2017-08-23 06:32:05 +08:00
|
|
|
fn process_tcp<'frame>(sockets: &mut SocketSet, timestamp: u64,
|
|
|
|
ip_repr: IpRepr, ip_payload: &'frame [u8]) ->
|
2017-08-30 03:35:09 +08:00
|
|
|
Result<Packet<'frame>> {
|
2017-08-28 12:50:57 +08:00
|
|
|
let (src_addr, dst_addr) = (ip_repr.src_addr(), ip_repr.dst_addr());
|
|
|
|
let tcp_packet = TcpPacket::new_checked(ip_payload)?;
|
|
|
|
let tcp_repr = TcpRepr::parse(&tcp_packet, &src_addr, &dst_addr)?;
|
|
|
|
|
2017-06-26 00:08:32 +08:00
|
|
|
for tcp_socket in sockets.iter_mut().filter_map(
|
|
|
|
<Socket as AsSocket<TcpSocket>>::try_as_socket) {
|
2017-09-01 05:44:41 +08:00
|
|
|
if !tcp_socket.accepts(&ip_repr, &tcp_repr) { continue }
|
|
|
|
|
2017-08-28 12:50:57 +08:00
|
|
|
match tcp_socket.process(timestamp, &ip_repr, &tcp_repr) {
|
2017-07-24 15:01:35 +08:00
|
|
|
// The packet is valid and handled by socket.
|
2017-08-30 03:35:09 +08:00
|
|
|
Ok(reply) => return Ok(reply.map_or(Packet::None, Packet::Tcp)),
|
2017-09-01 05:44:41 +08:00
|
|
|
// The packet is malformed, or doesn't match the socket state,
|
|
|
|
// or the socket buffer is full.
|
2017-06-26 00:08:32 +08:00
|
|
|
Err(e) => return Err(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-23 06:32:05 +08:00
|
|
|
if tcp_repr.control == TcpControl::Rst {
|
|
|
|
// Never reply to a TCP RST packet with another TCP RST packet.
|
2017-08-30 03:35:09 +08:00
|
|
|
Ok(Packet::None)
|
2017-08-23 06:32:05 +08:00
|
|
|
} else {
|
2017-08-28 12:50:57 +08:00
|
|
|
// The packet wasn't handled by a socket, send a TCP RST packet.
|
2017-08-30 03:35:09 +08:00
|
|
|
Ok(Packet::Tcp(TcpSocket::rst_reply(&ip_repr, &tcp_repr)))
|
2017-08-28 10:11:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-30 03:35:09 +08:00
|
|
|
fn dispatch(&mut self, timestamp: u64, packet: Packet) -> Result<()> {
|
|
|
|
match packet {
|
|
|
|
Packet::Arp(arp_repr) => {
|
2017-08-23 06:32:05 +08:00
|
|
|
let dst_hardware_addr =
|
|
|
|
match arp_repr {
|
|
|
|
ArpRepr::EthernetIpv4 { target_hardware_addr, .. } => target_hardware_addr,
|
|
|
|
_ => unreachable!()
|
|
|
|
};
|
2016-12-12 15:19:53 +08:00
|
|
|
|
2017-08-28 13:49:56 +08:00
|
|
|
self.dispatch_ethernet(timestamp, arp_repr.buffer_len(), |mut frame| {
|
2017-08-23 06:32:05 +08:00
|
|
|
frame.set_dst_addr(dst_hardware_addr);
|
|
|
|
frame.set_ethertype(EthernetProtocol::Arp);
|
2016-12-20 08:07:02 +08:00
|
|
|
|
2017-08-23 06:32:05 +08:00
|
|
|
let mut packet = ArpPacket::new(frame.payload_mut());
|
|
|
|
arp_repr.emit(&mut packet);
|
|
|
|
})
|
2016-12-13 07:22:59 +08:00
|
|
|
},
|
2017-08-30 03:35:09 +08:00
|
|
|
Packet::Icmpv4(ipv4_repr, icmpv4_repr) => {
|
2017-08-28 13:49:56 +08:00
|
|
|
self.dispatch_ip(timestamp, IpRepr::Ipv4(ipv4_repr), |_ip_repr, payload| {
|
2017-08-23 06:32:05 +08:00
|
|
|
icmpv4_repr.emit(&mut Icmpv4Packet::new(payload));
|
|
|
|
})
|
2016-12-12 15:19:53 +08:00
|
|
|
}
|
2017-08-30 03:35:09 +08:00
|
|
|
Packet::Raw((ip_repr, raw_packet)) => {
|
2017-08-28 13:49:56 +08:00
|
|
|
self.dispatch_ip(timestamp, ip_repr, |_ip_repr, payload| {
|
2017-08-28 11:50:40 +08:00
|
|
|
payload.copy_from_slice(raw_packet);
|
|
|
|
})
|
|
|
|
}
|
2017-08-30 03:35:09 +08:00
|
|
|
Packet::Udp((ip_repr, udp_repr)) => {
|
2017-08-28 13:49:56 +08:00
|
|
|
self.dispatch_ip(timestamp, ip_repr, |ip_repr, payload| {
|
2017-08-28 11:50:40 +08:00
|
|
|
udp_repr.emit(&mut UdpPacket::new(payload),
|
2017-08-23 06:32:05 +08:00
|
|
|
&ip_repr.src_addr(), &ip_repr.dst_addr());
|
|
|
|
})
|
2016-12-20 08:07:02 +08:00
|
|
|
}
|
2017-08-30 21:55:33 +08:00
|
|
|
Packet::Tcp((ip_repr, mut tcp_repr)) => {
|
|
|
|
let limits = self.device.limits();
|
2017-08-28 13:49:56 +08:00
|
|
|
self.dispatch_ip(timestamp, ip_repr, |ip_repr, payload| {
|
2017-08-30 21:55:33 +08:00
|
|
|
// This is a terrible hack to make TCP performance more acceptable on systems
|
|
|
|
// where the TCP buffers are significantly larger than network buffers,
|
|
|
|
// e.g. a 64 kB TCP receive buffer (and so, when empty, a 64k window)
|
|
|
|
// together with four 1500 B Ethernet receive buffers. If left untreated,
|
|
|
|
// this would result in our peer pushing our window and sever packet loss.
|
|
|
|
//
|
|
|
|
// I'm really not happy about this "solution" but I don't know what else to do.
|
|
|
|
if let Some(max_burst_size) = limits.max_burst_size {
|
|
|
|
let mut max_segment_size = limits.max_transmission_unit;
|
|
|
|
max_segment_size -= EthernetFrame::<&[u8]>::header_len();
|
|
|
|
max_segment_size -= ip_repr.buffer_len();
|
|
|
|
max_segment_size -= tcp_repr.header_len();
|
|
|
|
|
|
|
|
let max_window_size = max_burst_size * max_segment_size;
|
|
|
|
if tcp_repr.window_len as usize > max_window_size {
|
|
|
|
tcp_repr.window_len = max_window_size as u16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-28 11:50:40 +08:00
|
|
|
tcp_repr.emit(&mut TcpPacket::new(payload),
|
|
|
|
&ip_repr.src_addr(), &ip_repr.dst_addr());
|
2017-08-28 10:11:04 +08:00
|
|
|
})
|
2016-12-15 13:15:00 +08:00
|
|
|
}
|
2017-08-30 03:35:09 +08:00
|
|
|
Packet::None => Ok(())
|
2016-12-12 15:19:53 +08:00
|
|
|
}
|
|
|
|
}
|
2017-08-28 13:49:56 +08:00
|
|
|
|
|
|
|
fn dispatch_ethernet<F>(&mut self, timestamp: u64, buffer_len: usize, f: F) -> Result<()>
|
|
|
|
where F: FnOnce(EthernetFrame<&mut [u8]>) {
|
|
|
|
let tx_len = EthernetFrame::<&[u8]>::buffer_len(buffer_len);
|
|
|
|
let mut tx_buffer = self.device.transmit(timestamp, tx_len)?;
|
|
|
|
debug_assert!(tx_buffer.as_ref().len() == tx_len);
|
|
|
|
|
|
|
|
let mut frame = EthernetFrame::new(tx_buffer.as_mut());
|
|
|
|
frame.set_src_addr(self.hardware_addr);
|
|
|
|
|
|
|
|
f(frame);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn lookup_hardware_addr(&mut self, timestamp: u64,
|
|
|
|
src_addr: &IpAddress, dst_addr: &IpAddress) ->
|
|
|
|
Result<EthernetAddress> {
|
|
|
|
if let Some(hardware_addr) = self.arp_cache.lookup(dst_addr) {
|
|
|
|
return Ok(hardware_addr)
|
|
|
|
}
|
|
|
|
|
|
|
|
if dst_addr.is_broadcast() {
|
2017-09-21 05:52:28 +08:00
|
|
|
return Ok(EthernetAddress::BROADCAST)
|
2017-08-28 13:49:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
match (src_addr, dst_addr) {
|
|
|
|
(&IpAddress::Ipv4(src_addr), &IpAddress::Ipv4(dst_addr)) => {
|
|
|
|
net_debug!("address {} not in ARP cache, sending request",
|
|
|
|
dst_addr);
|
|
|
|
|
|
|
|
let arp_repr = ArpRepr::EthernetIpv4 {
|
|
|
|
operation: ArpOperation::Request,
|
|
|
|
source_hardware_addr: self.hardware_addr,
|
|
|
|
source_protocol_addr: src_addr,
|
2017-09-21 05:52:28 +08:00
|
|
|
target_hardware_addr: EthernetAddress::BROADCAST,
|
2017-08-28 13:49:56 +08:00
|
|
|
target_protocol_addr: dst_addr,
|
|
|
|
};
|
|
|
|
|
|
|
|
self.dispatch_ethernet(timestamp, arp_repr.buffer_len(), |mut frame| {
|
2017-09-21 05:52:28 +08:00
|
|
|
frame.set_dst_addr(EthernetAddress::BROADCAST);
|
2017-08-28 13:49:56 +08:00
|
|
|
frame.set_ethertype(EthernetProtocol::Arp);
|
|
|
|
|
|
|
|
arp_repr.emit(&mut ArpPacket::new(frame.payload_mut()))
|
|
|
|
})?;
|
|
|
|
|
|
|
|
Err(Error::Unaddressable)
|
|
|
|
}
|
|
|
|
_ => unreachable!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn dispatch_ip<F>(&mut self, timestamp: u64, ip_repr: IpRepr, f: F) -> Result<()>
|
|
|
|
where F: FnOnce(IpRepr, &mut [u8]) {
|
|
|
|
let ip_repr = ip_repr.lower(&self.protocol_addrs)?;
|
|
|
|
|
|
|
|
let dst_hardware_addr =
|
2017-08-30 03:35:09 +08:00
|
|
|
self.lookup_hardware_addr(timestamp, &ip_repr.src_addr(), &ip_repr.dst_addr())?;
|
2017-08-28 13:49:56 +08:00
|
|
|
|
|
|
|
self.dispatch_ethernet(timestamp, ip_repr.total_len(), |mut frame| {
|
|
|
|
frame.set_dst_addr(dst_hardware_addr);
|
|
|
|
match ip_repr {
|
|
|
|
IpRepr::Ipv4(_) => frame.set_ethertype(EthernetProtocol::Ipv4),
|
|
|
|
_ => unreachable!()
|
|
|
|
}
|
|
|
|
|
|
|
|
ip_repr.emit(frame.payload_mut());
|
|
|
|
|
|
|
|
let payload = &mut frame.payload_mut()[ip_repr.buffer_len()..];
|
|
|
|
f(ip_repr, payload)
|
|
|
|
})
|
|
|
|
}
|
2016-12-12 10:39:46 +08:00
|
|
|
}
|