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};
|
2016-12-21 03:18:35 +08:00
|
|
|
use wire::{TcpPacket, TcpRepr, TcpControl};
|
2017-06-26 00:08:32 +08:00
|
|
|
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-06-26 00:08:32 +08:00
|
|
|
enum Response<'a> {
|
|
|
|
Nop,
|
|
|
|
Arp(ArpRepr),
|
|
|
|
Icmpv4(Ipv4Repr, Icmpv4Repr<'a>),
|
|
|
|
Tcpv4(Ipv4Repr, TcpRepr<'a>)
|
|
|
|
}
|
|
|
|
|
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-01-11 13:25:54 +08:00
|
|
|
/// Receive and process a packet, if available, and then transmit a packet, if necessary,
|
|
|
|
/// handling the given set of sockets.
|
2016-12-31 16:35:07 +08:00
|
|
|
///
|
|
|
|
/// The timestamp is a monotonically increasing number of milliseconds.
|
2017-07-27 21:51:02 +08:00
|
|
|
pub fn poll(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<()> {
|
2016-12-20 08:07:02 +08:00
|
|
|
// First, transmit any outgoing packets.
|
|
|
|
loop {
|
2017-06-25 00:34:32 +08:00
|
|
|
if self.emit(sockets, timestamp)? { break }
|
2016-12-20 08:07:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now, receive any incoming packets.
|
2017-07-23 17:44:54 +08:00
|
|
|
let rx_buffer = self.device.receive(timestamp)?;
|
2017-06-25 00:34:32 +08:00
|
|
|
let eth_frame = EthernetFrame::new_checked(&rx_buffer)?;
|
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 {
|
|
|
|
return Ok(())
|
|
|
|
}
|
2017-03-06 11:58:19 +08:00
|
|
|
|
2017-06-26 00:08:32 +08:00
|
|
|
let response = match eth_frame.ethertype() {
|
|
|
|
EthernetProtocol::Arp =>
|
|
|
|
self.process_arp(ð_frame)?,
|
|
|
|
EthernetProtocol::Ipv4 =>
|
|
|
|
self.process_ipv4(sockets, timestamp, ð_frame)?,
|
|
|
|
// Drop all other traffic.
|
|
|
|
_ => return Err(Error::Unrecognized),
|
|
|
|
};
|
2016-12-13 07:22:59 +08:00
|
|
|
|
2017-07-23 17:44:54 +08:00
|
|
|
self.send_response(timestamp, response)
|
2017-06-26 00:08:32 +08:00
|
|
|
}
|
2016-12-23 15:31:02 +08:00
|
|
|
|
2017-06-26 00:08:32 +08:00
|
|
|
// Snoop all ARP traffic, and respond to ARP packets directed at us.
|
|
|
|
fn process_arp<'frame, T: AsRef<[u8]>>
|
|
|
|
(&mut self, eth_frame: &EthernetFrame<&'frame T>) ->
|
2017-07-27 21:51:02 +08:00
|
|
|
Result<Response<'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 {
|
|
|
|
// Respond to ARP requests aimed at us, and fill the ARP cache
|
|
|
|
// from all ARP requests, including gratuitous.
|
|
|
|
ArpRepr::EthernetIpv4 {
|
|
|
|
operation: ArpOperation::Request,
|
|
|
|
source_hardware_addr, source_protocol_addr,
|
|
|
|
target_protocol_addr, ..
|
|
|
|
} => {
|
|
|
|
if source_protocol_addr.is_unicast() && source_hardware_addr.is_unicast() {
|
|
|
|
self.arp_cache.fill(&source_protocol_addr.into(),
|
|
|
|
&source_hardware_addr);
|
2017-03-07 14:32:09 +08:00
|
|
|
}
|
2016-12-23 15:31:02 +08:00
|
|
|
|
2017-06-26 00:08:32 +08:00
|
|
|
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)
|
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
|
|
|
// Fill the ARP cache from gratuitous ARP replies.
|
|
|
|
ArpRepr::EthernetIpv4 {
|
|
|
|
operation: ArpOperation::Reply,
|
|
|
|
source_hardware_addr, source_protocol_addr, ..
|
|
|
|
} => {
|
|
|
|
if source_protocol_addr.is_unicast() && source_hardware_addr.is_unicast() {
|
|
|
|
self.arp_cache.fill(&source_protocol_addr.into(),
|
|
|
|
&source_hardware_addr);
|
2016-12-13 07:22:59 +08:00
|
|
|
}
|
2017-06-26 00:08:32 +08:00
|
|
|
Ok(Response::Nop)
|
2016-12-13 07:22:59 +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-07-27 21:51:02 +08:00
|
|
|
Result<Response<'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.
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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) {
|
|
|
|
match raw_socket.process(timestamp, &IpRepr::Ipv4(ipv4_repr),
|
|
|
|
ipv4_packet.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-07-24 15:01:35 +08:00
|
|
|
// The packet isn't addressed to the socket, or cannot be accepted by it.
|
|
|
|
Err(Error::Rejected) | Err(Error::Exhausted) => (),
|
|
|
|
// Raw sockets either accept or reject packets, not parse them.
|
2017-06-26 00:08:32 +08:00
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !self.has_protocol_addr(ipv4_repr.dst_addr) {
|
|
|
|
// Ignore IP packets not directed at us.
|
|
|
|
return Ok(Response::Nop)
|
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 =>
|
|
|
|
Self::process_icmpv4(ipv4_repr, ipv4_packet.payload()),
|
|
|
|
IpProtocol::Tcp =>
|
|
|
|
Self::process_tcpv4(sockets, timestamp, ipv4_repr, ipv4_packet.payload()),
|
|
|
|
IpProtocol::Udp =>
|
|
|
|
Self::process_udpv4(sockets, timestamp, ipv4_repr, ipv4_packet.payload()),
|
2017-07-24 14:56:06 +08:00
|
|
|
_ if handled_by_raw_socket =>
|
|
|
|
Ok(Response::Nop),
|
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,
|
|
|
|
data: &ipv4_packet.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: icmp_reply_repr.buffer_len()
|
|
|
|
};
|
|
|
|
Ok(Response::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-07-27 21:51:02 +08:00
|
|
|
Result<Response<'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.
|
|
|
|
Icmpv4Repr::EchoRequest {
|
|
|
|
ident, seq_no, data
|
|
|
|
} => {
|
|
|
|
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()
|
|
|
|
};
|
|
|
|
Ok(Response::Icmpv4(ipv4_reply_repr, icmp_reply_repr))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ignore any echo replies.
|
|
|
|
Icmpv4Repr::EchoReply { .. } => Ok(Response::Nop),
|
|
|
|
|
|
|
|
// FIXME: do something correct here?
|
|
|
|
_ => Err(Error::Unrecognized),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-24 14:56:06 +08:00
|
|
|
fn process_udpv4<'frame>(sockets: &mut SocketSet, timestamp: u64,
|
|
|
|
ipv4_repr: Ipv4Repr, ip_payload: &'frame [u8]) ->
|
2017-07-27 21:51:02 +08:00
|
|
|
Result<Response<'frame>> {
|
2017-07-24 14:56:06 +08:00
|
|
|
let ip_repr = IpRepr::Ipv4(ipv4_repr);
|
|
|
|
|
|
|
|
for udp_socket in sockets.iter_mut().filter_map(
|
|
|
|
<Socket as AsSocket<UdpSocket>>::try_as_socket) {
|
|
|
|
match udp_socket.process(timestamp, &ip_repr, ip_payload) {
|
2017-07-24 15:01:35 +08:00
|
|
|
// The packet is valid and handled by socket.
|
2017-07-24 14:56:06 +08:00
|
|
|
Ok(()) => return Ok(Response::Nop),
|
2017-07-24 15:01:35 +08:00
|
|
|
// The packet isn't addressed to the socket.
|
2017-07-24 14:56:06 +08:00
|
|
|
Err(Error::Rejected) => continue,
|
2017-07-24 15:01:35 +08:00
|
|
|
// The packet is malformed, or addressed to the socket but cannot be accepted.
|
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-07-24 14:56:06 +08:00
|
|
|
let icmp_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: icmp_reply_repr.buffer_len()
|
|
|
|
};
|
|
|
|
Ok(Response::Icmpv4(ipv4_reply_repr, icmp_reply_repr))
|
|
|
|
}
|
|
|
|
|
2017-06-26 00:08:32 +08:00
|
|
|
fn process_tcpv4<'frame>(sockets: &mut SocketSet, timestamp: u64,
|
|
|
|
ipv4_repr: Ipv4Repr, ip_payload: &'frame [u8]) ->
|
2017-07-27 21:51:02 +08:00
|
|
|
Result<Response<'frame>> {
|
2017-06-26 00:08:32 +08:00
|
|
|
let ip_repr = IpRepr::Ipv4(ipv4_repr);
|
|
|
|
|
|
|
|
for tcp_socket in sockets.iter_mut().filter_map(
|
|
|
|
<Socket as AsSocket<TcpSocket>>::try_as_socket) {
|
|
|
|
match tcp_socket.process(timestamp, &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(()) => return Ok(Response::Nop),
|
2017-07-24 15:01:35 +08:00
|
|
|
// The packet isn't addressed to the socket.
|
2017-06-26 00:08:32 +08:00
|
|
|
// Send RST only if no other socket accepts the packet.
|
|
|
|
Err(Error::Rejected) => continue,
|
2017-07-24 15:01:35 +08:00
|
|
|
// The packet is malformed, or addressed to the socket but cannot be accepted.
|
2017-06-26 00:08:32 +08:00
|
|
|
Err(e) => return Err(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The packet wasn't handled by a socket, send a TCP RST packet.
|
|
|
|
let tcp_packet = TcpPacket::new_checked(ip_payload)?;
|
2017-06-26 00:08:32 +08:00
|
|
|
if tcp_packet.rst() {
|
|
|
|
// Don't reply to a TCP RST packet with another TCP RST packet.
|
|
|
|
return Ok(Response::Nop)
|
|
|
|
}
|
2017-06-26 00:08:32 +08:00
|
|
|
let tcp_reply_repr = TcpRepr {
|
|
|
|
src_port: tcp_packet.dst_port(),
|
|
|
|
dst_port: tcp_packet.src_port(),
|
|
|
|
control: TcpControl::Rst,
|
|
|
|
push: false,
|
|
|
|
seq_number: tcp_packet.ack_number(),
|
|
|
|
ack_number: Some(tcp_packet.seq_number() +
|
|
|
|
tcp_packet.segment_len()),
|
|
|
|
window_len: 0,
|
|
|
|
max_seg_size: None,
|
|
|
|
payload: &[]
|
|
|
|
};
|
|
|
|
let ipv4_reply_repr = Ipv4Repr {
|
|
|
|
src_addr: ipv4_repr.dst_addr,
|
|
|
|
dst_addr: ipv4_repr.src_addr,
|
|
|
|
protocol: IpProtocol::Tcp,
|
|
|
|
payload_len: tcp_reply_repr.buffer_len()
|
|
|
|
};
|
|
|
|
Ok(Response::Tcpv4(ipv4_reply_repr, tcp_reply_repr))
|
|
|
|
}
|
|
|
|
|
2017-07-27 21:51:02 +08:00
|
|
|
fn send_response(&mut self, timestamp: u64, response: Response) -> Result<()> {
|
2016-12-21 03:18:35 +08:00
|
|
|
macro_rules! ip_response {
|
2017-01-14 19:07:06 +08:00
|
|
|
($tx_buffer:ident, $frame:ident, $ip_repr:ident) => ({
|
2016-12-21 03:18:35 +08:00
|
|
|
let dst_hardware_addr =
|
2016-12-26 18:06:49 +08:00
|
|
|
match self.arp_cache.lookup(&$ip_repr.dst_addr.into()) {
|
2016-12-21 03:18:35 +08:00
|
|
|
None => return Err(Error::Unaddressable),
|
|
|
|
Some(hardware_addr) => hardware_addr
|
|
|
|
};
|
|
|
|
|
2017-08-06 23:09:05 +08:00
|
|
|
let tx_len = EthernetFrame::<&[u8]>::buffer_len($ip_repr.buffer_len() +
|
|
|
|
$ip_repr.payload_len);
|
|
|
|
$tx_buffer = self.device.transmit(timestamp, tx_len)?;
|
|
|
|
debug_assert!($tx_buffer.as_ref().len() == tx_len);
|
|
|
|
|
|
|
|
$frame = EthernetFrame::new(&mut $tx_buffer);
|
2016-12-21 03:18:35 +08:00
|
|
|
$frame.set_src_addr(self.hardware_addr);
|
|
|
|
$frame.set_dst_addr(dst_hardware_addr);
|
|
|
|
$frame.set_ethertype(EthernetProtocol::Ipv4);
|
|
|
|
|
Do not attempt to validate length of packets being emitted.
This is a form of an uninitialized read bug; although safe it caused
panics. In short, transmit buffers received from the network stack
should be considered uninitialized (in practice they will often
contain previously transmitted packets or parts thereof). Wrapping
them with the only method we had (e.g. Ipv4Packet) treated the buffer
as if it contained a valid incoming packet, which can easily fail
with Error::Truncated.
This commit splits every `fn new(buffer: T) -> Result<Self, Error>`
method on a `Packet` into three smaller ones:
* `fn check_len(&self) -> Result<(), Error>`, purely a validator;
* `fn new(T) -> Self`, purely a wrapper;
* `fn new_checked(T) -> Result<Self, Error>`, a validating wrapper.
This makes it easy to process ingress packets (using `new_checked`),
egress packets (using `new`), and, if needed, maintain the invariants
at any point during packet construction (using `check_len`).
Fixes #17.
2017-06-24 17:15:22 +08:00
|
|
|
let mut ip_packet = Ipv4Packet::new($frame.payload_mut());
|
2017-01-14 19:07:06 +08:00
|
|
|
$ip_repr.emit(&mut ip_packet);
|
2016-12-21 03:18:35 +08:00
|
|
|
ip_packet
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-12-13 07:22:59 +08:00
|
|
|
match response {
|
2016-12-12 15:19:53 +08:00
|
|
|
Response::Arp(repr) => {
|
2016-12-20 07:50:04 +08:00
|
|
|
let tx_len = EthernetFrame::<&[u8]>::buffer_len(repr.buffer_len());
|
2017-07-23 17:44:54 +08:00
|
|
|
let mut tx_buffer = self.device.transmit(timestamp, tx_len)?;
|
2017-08-06 23:09:05 +08:00
|
|
|
debug_assert!(tx_buffer.as_ref().len() == tx_len);
|
|
|
|
|
|
|
|
let mut frame = EthernetFrame::new(&mut tx_buffer);
|
2016-12-15 13:15:00 +08:00
|
|
|
frame.set_src_addr(self.hardware_addr);
|
2016-12-13 01:26:06 +08:00
|
|
|
frame.set_dst_addr(match repr {
|
2016-12-12 20:30:35 +08:00
|
|
|
ArpRepr::EthernetIpv4 { target_hardware_addr, .. } => target_hardware_addr,
|
|
|
|
_ => unreachable!()
|
|
|
|
});
|
2016-12-20 21:54:11 +08:00
|
|
|
frame.set_ethertype(EthernetProtocol::Arp);
|
2016-12-12 15:19:53 +08:00
|
|
|
|
Do not attempt to validate length of packets being emitted.
This is a form of an uninitialized read bug; although safe it caused
panics. In short, transmit buffers received from the network stack
should be considered uninitialized (in practice they will often
contain previously transmitted packets or parts thereof). Wrapping
them with the only method we had (e.g. Ipv4Packet) treated the buffer
as if it contained a valid incoming packet, which can easily fail
with Error::Truncated.
This commit splits every `fn new(buffer: T) -> Result<Self, Error>`
method on a `Packet` into three smaller ones:
* `fn check_len(&self) -> Result<(), Error>`, purely a validator;
* `fn new(T) -> Self`, purely a wrapper;
* `fn new_checked(T) -> Result<Self, Error>`, a validating wrapper.
This makes it easy to process ingress packets (using `new_checked`),
egress packets (using `new`), and, if needed, maintain the invariants
at any point during packet construction (using `check_len`).
Fixes #17.
2017-06-24 17:15:22 +08:00
|
|
|
let mut packet = ArpPacket::new(frame.payload_mut());
|
2016-12-20 08:07:02 +08:00
|
|
|
repr.emit(&mut packet);
|
|
|
|
|
|
|
|
Ok(())
|
2016-12-13 07:22:59 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
Response::Icmpv4(ip_repr, icmp_repr) => {
|
2016-12-21 03:18:35 +08:00
|
|
|
let mut tx_buffer;
|
|
|
|
let mut frame;
|
2017-01-14 19:07:06 +08:00
|
|
|
let mut ip_packet = ip_response!(tx_buffer, frame, ip_repr);
|
Do not attempt to validate length of packets being emitted.
This is a form of an uninitialized read bug; although safe it caused
panics. In short, transmit buffers received from the network stack
should be considered uninitialized (in practice they will often
contain previously transmitted packets or parts thereof). Wrapping
them with the only method we had (e.g. Ipv4Packet) treated the buffer
as if it contained a valid incoming packet, which can easily fail
with Error::Truncated.
This commit splits every `fn new(buffer: T) -> Result<Self, Error>`
method on a `Packet` into three smaller ones:
* `fn check_len(&self) -> Result<(), Error>`, purely a validator;
* `fn new(T) -> Self`, purely a wrapper;
* `fn new_checked(T) -> Result<Self, Error>`, a validating wrapper.
This makes it easy to process ingress packets (using `new_checked`),
egress packets (using `new`), and, if needed, maintain the invariants
at any point during packet construction (using `check_len`).
Fixes #17.
2017-06-24 17:15:22 +08:00
|
|
|
let mut icmp_packet = Icmpv4Packet::new(ip_packet.payload_mut());
|
2016-12-13 07:22:59 +08:00
|
|
|
icmp_repr.emit(&mut icmp_packet);
|
2016-12-21 03:18:35 +08:00
|
|
|
Ok(())
|
|
|
|
}
|
2016-12-20 08:07:02 +08:00
|
|
|
|
2016-12-21 03:18:35 +08:00
|
|
|
Response::Tcpv4(ip_repr, tcp_repr) => {
|
|
|
|
let mut tx_buffer;
|
|
|
|
let mut frame;
|
2017-01-14 19:07:06 +08:00
|
|
|
let mut ip_packet = ip_response!(tx_buffer, frame, ip_repr);
|
Do not attempt to validate length of packets being emitted.
This is a form of an uninitialized read bug; although safe it caused
panics. In short, transmit buffers received from the network stack
should be considered uninitialized (in practice they will often
contain previously transmitted packets or parts thereof). Wrapping
them with the only method we had (e.g. Ipv4Packet) treated the buffer
as if it contained a valid incoming packet, which can easily fail
with Error::Truncated.
This commit splits every `fn new(buffer: T) -> Result<Self, Error>`
method on a `Packet` into three smaller ones:
* `fn check_len(&self) -> Result<(), Error>`, purely a validator;
* `fn new(T) -> Self`, purely a wrapper;
* `fn new_checked(T) -> Result<Self, Error>`, a validating wrapper.
This makes it easy to process ingress packets (using `new_checked`),
egress packets (using `new`), and, if needed, maintain the invariants
at any point during packet construction (using `check_len`).
Fixes #17.
2017-06-24 17:15:22 +08:00
|
|
|
let mut tcp_packet = TcpPacket::new(ip_packet.payload_mut());
|
2016-12-21 03:18:35 +08:00
|
|
|
tcp_repr.emit(&mut tcp_packet,
|
|
|
|
&IpAddress::Ipv4(ip_repr.src_addr),
|
|
|
|
&IpAddress::Ipv4(ip_repr.dst_addr));
|
2016-12-20 08:07:02 +08:00
|
|
|
Ok(())
|
2016-12-12 15:19:53 +08:00
|
|
|
}
|
2016-12-13 07:22:59 +08:00
|
|
|
|
2016-12-15 13:15:00 +08:00
|
|
|
Response::Nop => {
|
2016-12-20 08:07:02 +08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-27 21:51:02 +08:00
|
|
|
fn emit(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<bool> {
|
2016-12-20 08:07:02 +08:00
|
|
|
// Borrow checker is being overly careful around closures, so we have
|
|
|
|
// to hack around that.
|
|
|
|
let src_hardware_addr = self.hardware_addr;
|
2017-01-10 19:37:12 +08:00
|
|
|
let src_protocol_addrs = self.protocol_addrs.as_ref();
|
2016-12-20 08:07:02 +08:00
|
|
|
let arp_cache = &mut self.arp_cache;
|
|
|
|
let device = &mut self.device;
|
2017-03-07 18:56:48 +08:00
|
|
|
|
|
|
|
let mut limits = device.limits();
|
|
|
|
limits.max_transmission_unit -= EthernetFrame::<&[u8]>::header_len();
|
2016-12-20 08:07:02 +08:00
|
|
|
|
|
|
|
let mut nothing_to_transmit = true;
|
2017-01-11 13:25:54 +08:00
|
|
|
for socket in sockets.iter_mut() {
|
2017-03-07 18:56:48 +08:00
|
|
|
let result = socket.dispatch(timestamp, &limits, &mut |repr, payload| {
|
2017-06-25 00:34:32 +08:00
|
|
|
let repr = repr.lower(src_protocol_addrs)?;
|
2016-12-20 08:07:02 +08:00
|
|
|
|
2017-03-05 12:59:51 +08:00
|
|
|
match arp_cache.lookup(&repr.dst_addr()) {
|
|
|
|
Some(dst_hardware_addr) => {
|
|
|
|
let tx_len = EthernetFrame::<&[u8]>::buffer_len(repr.buffer_len() +
|
|
|
|
payload.buffer_len());
|
2017-07-23 17:44:54 +08:00
|
|
|
let mut tx_buffer = device.transmit(timestamp, tx_len)?;
|
2017-08-06 23:09:05 +08:00
|
|
|
debug_assert!(tx_buffer.as_ref().len() == tx_len);
|
|
|
|
|
|
|
|
let mut frame = EthernetFrame::new(&mut tx_buffer);
|
2017-03-05 12:59:51 +08:00
|
|
|
frame.set_src_addr(src_hardware_addr);
|
|
|
|
frame.set_dst_addr(dst_hardware_addr);
|
|
|
|
frame.set_ethertype(EthernetProtocol::Ipv4);
|
|
|
|
|
|
|
|
repr.emit(frame.payload_mut());
|
|
|
|
|
Do not attempt to validate length of packets being emitted.
This is a form of an uninitialized read bug; although safe it caused
panics. In short, transmit buffers received from the network stack
should be considered uninitialized (in practice they will often
contain previously transmitted packets or parts thereof). Wrapping
them with the only method we had (e.g. Ipv4Packet) treated the buffer
as if it contained a valid incoming packet, which can easily fail
with Error::Truncated.
This commit splits every `fn new(buffer: T) -> Result<Self, Error>`
method on a `Packet` into three smaller ones:
* `fn check_len(&self) -> Result<(), Error>`, purely a validator;
* `fn new(T) -> Self`, purely a wrapper;
* `fn new_checked(T) -> Result<Self, Error>`, a validating wrapper.
This makes it easy to process ingress packets (using `new_checked`),
egress packets (using `new`), and, if needed, maintain the invariants
at any point during packet construction (using `check_len`).
Fixes #17.
2017-06-24 17:15:22 +08:00
|
|
|
let mut ip_packet = Ipv4Packet::new(frame.payload_mut());
|
2017-03-05 12:59:51 +08:00
|
|
|
payload.emit(&repr, ip_packet.payload_mut());
|
|
|
|
}
|
|
|
|
|
|
|
|
None => {
|
|
|
|
let (src_addr, dst_addr) =
|
|
|
|
match (repr.src_addr(), repr.dst_addr()) {
|
|
|
|
(IpAddress::Ipv4(src_addr), IpAddress::Ipv4(dst_addr)) =>
|
|
|
|
(src_addr, dst_addr),
|
2017-06-22 08:38:11 +08:00
|
|
|
// We've lowered all addresses to a concrete form.
|
|
|
|
_ => unreachable!()
|
2017-03-05 12:59:51 +08:00
|
|
|
};
|
2016-12-20 08:07:02 +08:00
|
|
|
|
2017-03-05 12:59:51 +08:00
|
|
|
let payload = ArpRepr::EthernetIpv4 {
|
|
|
|
operation: ArpOperation::Request,
|
|
|
|
source_hardware_addr: src_hardware_addr,
|
|
|
|
source_protocol_addr: src_addr,
|
|
|
|
target_hardware_addr: EthernetAddress::default(),
|
|
|
|
target_protocol_addr: dst_addr,
|
|
|
|
};
|
|
|
|
|
|
|
|
let tx_len = EthernetFrame::<&[u8]>::buffer_len(payload.buffer_len());
|
2017-07-23 17:44:54 +08:00
|
|
|
let mut tx_buffer = device.transmit(timestamp, tx_len)?;
|
2017-08-06 23:09:05 +08:00
|
|
|
debug_assert!(tx_buffer.as_ref().len() == tx_len);
|
|
|
|
|
|
|
|
let mut frame = EthernetFrame::new(&mut tx_buffer);
|
2017-03-05 12:59:51 +08:00
|
|
|
frame.set_src_addr(src_hardware_addr);
|
|
|
|
frame.set_dst_addr(EthernetAddress([0xff; 6]));
|
|
|
|
frame.set_ethertype(EthernetProtocol::Arp);
|
|
|
|
|
Do not attempt to validate length of packets being emitted.
This is a form of an uninitialized read bug; although safe it caused
panics. In short, transmit buffers received from the network stack
should be considered uninitialized (in practice they will often
contain previously transmitted packets or parts thereof). Wrapping
them with the only method we had (e.g. Ipv4Packet) treated the buffer
as if it contained a valid incoming packet, which can easily fail
with Error::Truncated.
This commit splits every `fn new(buffer: T) -> Result<Self, Error>`
method on a `Packet` into three smaller ones:
* `fn check_len(&self) -> Result<(), Error>`, purely a validator;
* `fn new(T) -> Self`, purely a wrapper;
* `fn new_checked(T) -> Result<Self, Error>`, a validating wrapper.
This makes it easy to process ingress packets (using `new_checked`),
egress packets (using `new`), and, if needed, maintain the invariants
at any point during packet construction (using `check_len`).
Fixes #17.
2017-06-24 17:15:22 +08:00
|
|
|
let mut arp_packet = ArpPacket::new(frame.payload_mut());
|
2017-03-05 12:59:51 +08:00
|
|
|
payload.emit(&mut arp_packet);
|
|
|
|
}
|
|
|
|
}
|
2016-12-20 08:07:02 +08:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
|
|
|
|
match result {
|
|
|
|
Ok(()) => {
|
|
|
|
nothing_to_transmit = false;
|
|
|
|
break
|
2016-12-15 13:15:00 +08:00
|
|
|
}
|
2016-12-20 08:07:02 +08:00
|
|
|
Err(Error::Exhausted) => continue,
|
|
|
|
Err(e) => return Err(e)
|
2016-12-15 13:15:00 +08:00
|
|
|
}
|
2016-12-12 15:19:53 +08:00
|
|
|
}
|
2016-12-13 07:22:59 +08:00
|
|
|
|
2016-12-20 08:07:02 +08:00
|
|
|
Ok(nothing_to_transmit)
|
2016-12-12 15:19:53 +08:00
|
|
|
}
|
2016-12-12 10:39:46 +08:00
|
|
|
}
|