raw_socket: gracefully handle packet truncation errors
This commit is contained in:
parent
eebd8e431a
commit
287e4f2814
|
@ -850,8 +850,8 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
|
|||
match raw_socket.process(&ip_repr, ip_payload, &checksum_caps) {
|
||||
// The packet is valid and handled by socket.
|
||||
Ok(()) => handled_by_raw_socket = true,
|
||||
// The socket buffer is full.
|
||||
Err(Error::Exhausted) => (),
|
||||
// The socket buffer is full or the packet was truncated
|
||||
Err(Error::Exhausted) | Err(Error::Truncated) => (),
|
||||
// Raw sockets don't validate the packets in any way.
|
||||
Err(_) => unreachable!(),
|
||||
}
|
||||
|
@ -2667,6 +2667,67 @@ mod test {
|
|||
Ok(Packet::None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(feature = "proto-ipv4", feature = "socket-raw"))]
|
||||
fn test_raw_socket_truncated_packet() {
|
||||
use socket::{RawSocket, RawSocketBuffer, RawPacketMetadata};
|
||||
use wire::{IpVersion, Ipv4Packet, UdpPacket, UdpRepr};
|
||||
|
||||
let (mut iface, mut socket_set) = create_loopback();
|
||||
|
||||
let packets = 1;
|
||||
let rx_buffer = RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * 1]);
|
||||
let tx_buffer = RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * packets]);
|
||||
let raw_socket = RawSocket::new(IpVersion::Ipv4, IpProtocol::Udp, rx_buffer, tx_buffer);
|
||||
socket_set.add(raw_socket);
|
||||
|
||||
let src_addr = Ipv4Address([127, 0, 0, 2]);
|
||||
let dst_addr = Ipv4Address([127, 0, 0, 1]);
|
||||
|
||||
let udp_repr = UdpRepr {
|
||||
src_port: 67,
|
||||
dst_port: 68,
|
||||
payload: &[0x2a; 49] // 49 > 48, hence packet will be truncated
|
||||
};
|
||||
let mut bytes = vec![0xff; udp_repr.buffer_len()];
|
||||
let mut packet = UdpPacket::new_unchecked(&mut bytes[..]);
|
||||
udp_repr.emit(&mut packet, &src_addr.into(), &dst_addr.into(), &ChecksumCapabilities::default());
|
||||
let ipv4_repr = Ipv4Repr {
|
||||
src_addr: src_addr,
|
||||
dst_addr: dst_addr,
|
||||
protocol: IpProtocol::Udp,
|
||||
hop_limit: 64,
|
||||
payload_len: udp_repr.buffer_len()
|
||||
};
|
||||
|
||||
// Emit to ethernet frame
|
||||
let mut eth_bytes = vec![0u8;
|
||||
EthernetFrame::<&[u8]>::header_len() +
|
||||
ipv4_repr.buffer_len() + udp_repr.buffer_len()
|
||||
];
|
||||
let frame = {
|
||||
let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
|
||||
ipv4_repr.emit(
|
||||
&mut Ipv4Packet::new_unchecked(frame.payload_mut()),
|
||||
&ChecksumCapabilities::default());
|
||||
udp_repr.emit(
|
||||
&mut UdpPacket::new_unchecked(
|
||||
&mut frame.payload_mut()[ipv4_repr.buffer_len()..]),
|
||||
&src_addr.into(),
|
||||
&dst_addr.into(),
|
||||
&ChecksumCapabilities::default());
|
||||
EthernetFrame::new_unchecked(&*frame.into_inner())
|
||||
};
|
||||
|
||||
let frame = iface.inner.process_ipv4(&mut socket_set, Instant::from_millis(0), &frame);
|
||||
|
||||
// because the packet could not be handled we should send an Icmp message
|
||||
assert!(match frame {
|
||||
Ok(Packet::Icmpv4(_)) => true,
|
||||
_ => false,
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(feature = "proto-ipv4", feature = "socket-raw", feature = "socket-udp"))]
|
||||
fn test_raw_socket_with_udp_socket() {
|
||||
|
|
Loading…
Reference in New Issue