Skip to content

Commit 0fedb1d

Browse files
MabezDevwhitequark
authored andcommitted
raw_socket: gracefully handle packet truncation errors
1 parent 14bad97 commit 0fedb1d

File tree

1 file changed

+63
-2
lines changed

1 file changed

+63
-2
lines changed

src/iface/ethernet.rs

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -850,8 +850,8 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
850850
match raw_socket.process(&ip_repr, ip_payload, &checksum_caps) {
851851
// The packet is valid and handled by socket.
852852
Ok(()) => handled_by_raw_socket = true,
853-
// The socket buffer is full.
854-
Err(Error::Exhausted) => (),
853+
// The socket buffer is full or the packet was truncated
854+
Err(Error::Exhausted) | Err(Error::Truncated) => (),
855855
// Raw sockets don't validate the packets in any way.
856856
Err(_) => unreachable!(),
857857
}
@@ -2667,6 +2667,67 @@ mod test {
26672667
Ok(Packet::None));
26682668
}
26692669

2670+
#[test]
2671+
#[cfg(all(feature = "proto-ipv4", feature = "socket-raw"))]
2672+
fn test_raw_socket_truncated_packet() {
2673+
use socket::{RawSocket, RawSocketBuffer, RawPacketMetadata};
2674+
use wire::{IpVersion, Ipv4Packet, UdpPacket, UdpRepr};
2675+
2676+
let (mut iface, mut socket_set) = create_loopback();
2677+
2678+
let packets = 1;
2679+
let rx_buffer = RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * 1]);
2680+
let tx_buffer = RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * packets]);
2681+
let raw_socket = RawSocket::new(IpVersion::Ipv4, IpProtocol::Udp, rx_buffer, tx_buffer);
2682+
socket_set.add(raw_socket);
2683+
2684+
let src_addr = Ipv4Address([127, 0, 0, 2]);
2685+
let dst_addr = Ipv4Address([127, 0, 0, 1]);
2686+
2687+
let udp_repr = UdpRepr {
2688+
src_port: 67,
2689+
dst_port: 68,
2690+
payload: &[0x2a; 49] // 49 > 48, hence packet will be truncated
2691+
};
2692+
let mut bytes = vec![0xff; udp_repr.buffer_len()];
2693+
let mut packet = UdpPacket::new_unchecked(&mut bytes[..]);
2694+
udp_repr.emit(&mut packet, &src_addr.into(), &dst_addr.into(), &ChecksumCapabilities::default());
2695+
let ipv4_repr = Ipv4Repr {
2696+
src_addr: src_addr,
2697+
dst_addr: dst_addr,
2698+
protocol: IpProtocol::Udp,
2699+
hop_limit: 64,
2700+
payload_len: udp_repr.buffer_len()
2701+
};
2702+
2703+
// Emit to ethernet frame
2704+
let mut eth_bytes = vec![0u8;
2705+
EthernetFrame::<&[u8]>::header_len() +
2706+
ipv4_repr.buffer_len() + udp_repr.buffer_len()
2707+
];
2708+
let frame = {
2709+
let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
2710+
ipv4_repr.emit(
2711+
&mut Ipv4Packet::new_unchecked(frame.payload_mut()),
2712+
&ChecksumCapabilities::default());
2713+
udp_repr.emit(
2714+
&mut UdpPacket::new_unchecked(
2715+
&mut frame.payload_mut()[ipv4_repr.buffer_len()..]),
2716+
&src_addr.into(),
2717+
&dst_addr.into(),
2718+
&ChecksumCapabilities::default());
2719+
EthernetFrame::new_unchecked(&*frame.into_inner())
2720+
};
2721+
2722+
let frame = iface.inner.process_ipv4(&mut socket_set, Instant::from_millis(0), &frame);
2723+
2724+
// because the packet could not be handled we should send an Icmp message
2725+
assert!(match frame {
2726+
Ok(Packet::Icmpv4(_)) => true,
2727+
_ => false,
2728+
});
2729+
}
2730+
26702731
#[test]
26712732
#[cfg(all(feature = "proto-ipv4", feature = "socket-raw", feature = "socket-udp"))]
26722733
fn test_raw_socket_with_udp_socket() {

0 commit comments

Comments
 (0)