|
@@ -876,13 +876,12 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
|
|
|
let ip_payload = ipv6_packet.payload();
|
|
|
|
|
|
#[cfg(feature = "socket-raw")]
|
|
|
- {
|
|
|
- if self.raw_socket_filter(sockets, &ipv6_repr.into(), ip_payload) {
|
|
|
- return Ok(Packet::None);
|
|
|
- }
|
|
|
- }
|
|
|
+ let handled_by_raw_socket = self.raw_socket_filter(sockets, &ipv6_repr.into(), ip_payload);
|
|
|
+ #[cfg(not(feature = "socket-raw"))]
|
|
|
+ let handled_by_raw_socket = false;
|
|
|
|
|
|
- self.process_nxt_hdr(sockets, timestamp, ipv6_repr, ipv6_repr.next_header, ip_payload)
|
|
|
+ self.process_nxt_hdr(sockets, timestamp, ipv6_repr, ipv6_repr.next_header,
|
|
|
+ handled_by_raw_socket, ip_payload)
|
|
|
}
|
|
|
|
|
|
/// Given the next header value forward the payload onto the correct process
|
|
@@ -890,7 +889,7 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
|
|
|
#[cfg(feature = "proto-ipv6")]
|
|
|
fn process_nxt_hdr<'frame>
|
|
|
(&mut self, sockets: &mut SocketSet, timestamp: Instant, ipv6_repr: Ipv6Repr,
|
|
|
- nxt_hdr: IpProtocol, ip_payload: &'frame [u8])
|
|
|
+ nxt_hdr: IpProtocol, handled_by_raw_socket: bool, ip_payload: &'frame [u8])
|
|
|
-> Result<Packet<'frame>>
|
|
|
{
|
|
|
match nxt_hdr {
|
|
@@ -899,14 +898,18 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
|
|
|
|
|
|
#[cfg(feature = "socket-udp")]
|
|
|
IpProtocol::Udp =>
|
|
|
- self.process_udp(sockets, ipv6_repr.into(), ip_payload),
|
|
|
+ self.process_udp(sockets, ipv6_repr.into(), handled_by_raw_socket, ip_payload),
|
|
|
|
|
|
#[cfg(feature = "socket-tcp")]
|
|
|
IpProtocol::Tcp =>
|
|
|
self.process_tcp(sockets, timestamp, ipv6_repr.into(), ip_payload),
|
|
|
|
|
|
IpProtocol::HopByHop =>
|
|
|
- self.process_hopbyhop(sockets, timestamp, ipv6_repr, ip_payload),
|
|
|
+ self.process_hopbyhop(sockets, timestamp, ipv6_repr, handled_by_raw_socket, ip_payload),
|
|
|
+
|
|
|
+ #[cfg(feature = "socket-raw")]
|
|
|
+ _ if handled_by_raw_socket =>
|
|
|
+ Ok(Packet::None),
|
|
|
|
|
|
_ => {
|
|
|
// Send back as much of the original payload as we can.
|
|
@@ -970,10 +973,6 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
|
|
|
}
|
|
|
|
|
|
match ipv4_repr.protocol {
|
|
|
- #[cfg(feature = "socket-raw")]
|
|
|
- _ if handled_by_raw_socket =>
|
|
|
- Ok(Packet::None),
|
|
|
-
|
|
|
IpProtocol::Icmp =>
|
|
|
self.process_icmpv4(sockets, ip_repr, ip_payload),
|
|
|
|
|
@@ -983,12 +982,16 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
|
|
|
|
|
|
#[cfg(feature = "socket-udp")]
|
|
|
IpProtocol::Udp =>
|
|
|
- self.process_udp(sockets, ip_repr, ip_payload),
|
|
|
+ self.process_udp(sockets, ip_repr, handled_by_raw_socket, ip_payload),
|
|
|
|
|
|
#[cfg(feature = "socket-tcp")]
|
|
|
IpProtocol::Tcp =>
|
|
|
self.process_tcp(sockets, timestamp, ip_repr, ip_payload),
|
|
|
|
|
|
+ #[cfg(feature = "socket-raw")]
|
|
|
+ _ if handled_by_raw_socket =>
|
|
|
+ Ok(Packet::None),
|
|
|
+
|
|
|
_ => {
|
|
|
// Send back as much of the original payload as we can.
|
|
|
let payload_len = icmp_reply_payload_len(ip_payload.len(), IPV4_MIN_MTU,
|
|
@@ -1170,7 +1173,8 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
|
|
|
|
|
|
#[cfg(feature = "proto-ipv6")]
|
|
|
fn process_hopbyhop<'frame>(&mut self, sockets: &mut SocketSet, timestamp: Instant,
|
|
|
- ipv6_repr: Ipv6Repr, ip_payload: &'frame [u8]) -> Result<Packet<'frame>>
|
|
|
+ ipv6_repr: Ipv6Repr, handled_by_raw_socket: bool,
|
|
|
+ ip_payload: &'frame [u8]) -> Result<Packet<'frame>>
|
|
|
{
|
|
|
let hbh_pkt = Ipv6HopByHopHeader::new_checked(ip_payload)?;
|
|
|
let hbh_repr = Ipv6HopByHopRepr::parse(&hbh_pkt)?;
|
|
@@ -1195,7 +1199,7 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
|
|
|
}
|
|
|
}
|
|
|
self.process_nxt_hdr(sockets, timestamp, ipv6_repr, hbh_repr.next_header,
|
|
|
- &ip_payload[hbh_repr.buffer_len()..])
|
|
|
+ handled_by_raw_socket, &ip_payload[hbh_repr.buffer_len()..])
|
|
|
}
|
|
|
|
|
|
#[cfg(feature = "proto-ipv4")]
|
|
@@ -1314,7 +1318,7 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
|
|
|
|
|
|
#[cfg(feature = "socket-udp")]
|
|
|
fn process_udp<'frame>(&self, sockets: &mut SocketSet,
|
|
|
- ip_repr: IpRepr, ip_payload: &'frame [u8]) ->
|
|
|
+ ip_repr: IpRepr, handled_by_raw_socket: bool, ip_payload: &'frame [u8]) ->
|
|
|
Result<Packet<'frame>>
|
|
|
{
|
|
|
let (src_addr, dst_addr) = (ip_repr.src_addr(), ip_repr.dst_addr());
|
|
@@ -1336,6 +1340,12 @@ impl<'b, 'c, 'e> InterfaceInner<'b, 'c, 'e> {
|
|
|
// The packet wasn't handled by a socket, send an ICMP port unreachable packet.
|
|
|
match ip_repr {
|
|
|
#[cfg(feature = "proto-ipv4")]
|
|
|
+ IpRepr::Ipv4(_) if handled_by_raw_socket =>
|
|
|
+ Ok(Packet::None),
|
|
|
+ #[cfg(feature = "proto-ipv6")]
|
|
|
+ IpRepr::Ipv6(_) if handled_by_raw_socket =>
|
|
|
+ Ok(Packet::None),
|
|
|
+ #[cfg(feature = "proto-ipv4")]
|
|
|
IpRepr::Ipv4(ipv4_repr) => {
|
|
|
let payload_len = icmp_reply_payload_len(ip_payload.len(), IPV4_MIN_MTU,
|
|
|
ipv4_repr.buffer_len());
|
|
@@ -1957,7 +1967,7 @@ mod test {
|
|
|
|
|
|
// Ensure that the unknown protocol triggers an error response.
|
|
|
// And we correctly handle no payload.
|
|
|
- assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr, data),
|
|
|
+ assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr, false, data),
|
|
|
Ok(expected_repr));
|
|
|
|
|
|
let ip_repr = IpRepr::Ipv4(Ipv4Repr {
|
|
@@ -1977,7 +1987,7 @@ mod test {
|
|
|
// ICMP error response when the destination address is a
|
|
|
// broadcast address and no socket is bound to the port.
|
|
|
assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr,
|
|
|
- packet_broadcast.into_inner()), Ok(Packet::None));
|
|
|
+ false, packet_broadcast.into_inner()), Ok(Packet::None));
|
|
|
}
|
|
|
|
|
|
#[test]
|
|
@@ -2040,7 +2050,7 @@ mod test {
|
|
|
&ChecksumCapabilities::default());
|
|
|
|
|
|
// Packet should be handled by bound UDP socket
|
|
|
- assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr, packet.into_inner()),
|
|
|
+ assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr, false, packet.into_inner()),
|
|
|
Ok(Packet::None));
|
|
|
|
|
|
{
|
|
@@ -2198,10 +2208,10 @@ mod test {
|
|
|
assert_eq!(expected_ip_repr.buffer_len() + expected_icmp_repr.buffer_len(), MIN_MTU);
|
|
|
// The expected packet and the generated packet are equal
|
|
|
#[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
|
|
|
- assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr.into(), payload),
|
|
|
+ assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr.into(), false, payload),
|
|
|
Ok(Packet::Icmpv4((expected_ip_repr, expected_icmp_repr))));
|
|
|
#[cfg(feature = "proto-ipv6")]
|
|
|
- assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr.into(), payload),
|
|
|
+ assert_eq!(iface.inner.process_udp(&mut socket_set, ip_repr.into(), false, payload),
|
|
|
Ok(Packet::Icmpv6((expected_ip_repr, expected_icmp_repr))));
|
|
|
}
|
|
|
|
|
@@ -2645,4 +2655,82 @@ mod test {
|
|
|
assert_eq!(iface.inner.process_ipv4(&mut socket_set, Instant::from_millis(0), &frame),
|
|
|
Ok(Packet::None));
|
|
|
}
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ #[cfg(all(feature = "proto-ipv4", feature = "socket-raw", feature = "socket-udp"))]
|
|
|
+ fn test_raw_socket_with_udp_socket() {
|
|
|
+ use socket::{UdpSocket, UdpSocketBuffer, UdpPacketMetadata,
|
|
|
+ RawSocket, RawSocketBuffer, RawPacketMetadata};
|
|
|
+ use wire::{IpVersion, IpEndpoint, Ipv4Packet, UdpPacket, UdpRepr};
|
|
|
+
|
|
|
+ static UDP_PAYLOAD: [u8; 5] = [0x48, 0x65, 0x6c, 0x6c, 0x6f];
|
|
|
+
|
|
|
+ let (mut iface, mut socket_set) = create_loopback();
|
|
|
+
|
|
|
+ let udp_rx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 15]);
|
|
|
+ let udp_tx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY], vec![0; 15]);
|
|
|
+ let udp_socket = UdpSocket::new(udp_rx_buffer, udp_tx_buffer);
|
|
|
+ let udp_socket_handle = socket_set.add(udp_socket);
|
|
|
+ {
|
|
|
+ // Bind the socket to port 68
|
|
|
+ let mut socket = socket_set.get::<UdpSocket>(udp_socket_handle);
|
|
|
+ assert_eq!(socket.bind(68), Ok(()));
|
|
|
+ assert!(!socket.can_recv());
|
|
|
+ assert!(socket.can_send());
|
|
|
+ }
|
|
|
+
|
|
|
+ let packets = 1;
|
|
|
+ let raw_rx_buffer = RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * 1]);
|
|
|
+ let raw_tx_buffer = RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * packets]);
|
|
|
+ let raw_socket = RawSocket::new(IpVersion::Ipv4, IpProtocol::Udp, raw_rx_buffer, raw_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: &UDP_PAYLOAD
|
|
|
+ };
|
|
|
+ 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())
|
|
|
+ };
|
|
|
+
|
|
|
+ assert_eq!(iface.inner.process_ipv4(&mut socket_set, Instant::from_millis(0), &frame),
|
|
|
+ Ok(Packet::None));
|
|
|
+
|
|
|
+ {
|
|
|
+ // Make sure the UDP socket can still receive in presence of a Raw socket that handles UDP
|
|
|
+ let mut socket = socket_set.get::<UdpSocket>(udp_socket_handle);
|
|
|
+ assert!(socket.can_recv());
|
|
|
+ assert_eq!(socket.recv(), Ok((&UDP_PAYLOAD[..], IpEndpoint::new(src_addr.into(), 67))));
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|