123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- #[cfg(feature = "proto-ipv4")]
- mod ipv4;
- #[cfg(feature = "proto-ipv6")]
- mod ipv6;
- #[cfg(feature = "proto-sixlowpan")]
- mod sixlowpan;
- #[cfg(feature = "proto-igmp")]
- use std::vec::Vec;
- use crate::tests::setup;
- use rstest::*;
- use super::*;
- use crate::iface::Interface;
- use crate::phy::ChecksumCapabilities;
- #[cfg(feature = "alloc")]
- use crate::phy::Loopback;
- use crate::time::Instant;
- #[allow(unused)]
- fn fill_slice(s: &mut [u8], val: u8) {
- for x in s.iter_mut() {
- *x = val
- }
- }
- #[cfg(feature = "proto-igmp")]
- fn recv_all(device: &mut crate::tests::TestingDevice, timestamp: Instant) -> Vec<Vec<u8>> {
- let mut pkts = Vec::new();
- while let Some((rx, _tx)) = device.receive(timestamp) {
- rx.consume(|pkt| {
- pkts.push(pkt.to_vec());
- });
- }
- pkts
- }
- #[derive(Debug, PartialEq)]
- #[cfg_attr(feature = "defmt", derive(defmt::Format))]
- struct MockTxToken;
- impl TxToken for MockTxToken {
- fn consume<R, F>(self, len: usize, f: F) -> R
- where
- F: FnOnce(&mut [u8]) -> R,
- {
- let mut junk = [0; 1536];
- f(&mut junk[..len])
- }
- }
- #[test]
- #[should_panic(expected = "The hardware address does not match the medium of the interface.")]
- #[cfg(all(feature = "medium-ip", feature = "medium-ethernet", feature = "alloc"))]
- fn test_new_panic() {
- let mut device = Loopback::new(Medium::Ethernet);
- let config = Config::new(HardwareAddress::Ip);
- Interface::new(config, &mut device, Instant::ZERO);
- }
- #[rstest]
- #[cfg(feature = "default")]
- fn test_handle_udp_broadcast(
- #[values(Medium::Ip, Medium::Ethernet, Medium::Ieee802154)] medium: Medium,
- ) {
- use crate::socket::udp;
- use crate::wire::IpEndpoint;
- static UDP_PAYLOAD: [u8; 5] = [0x48, 0x65, 0x6c, 0x6c, 0x6f];
- let (mut iface, mut sockets, _device) = setup(medium);
- let rx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 15]);
- let tx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 15]);
- let udp_socket = udp::Socket::new(rx_buffer, tx_buffer);
- let mut udp_bytes = vec![0u8; 13];
- let mut packet = UdpPacket::new_unchecked(&mut udp_bytes);
- let socket_handle = sockets.add(udp_socket);
- #[cfg(feature = "proto-ipv6")]
- let src_ip = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
- #[cfg(all(not(feature = "proto-ipv6"), feature = "proto-ipv4"))]
- let src_ip = Ipv4Address::new(0x7f, 0x00, 0x00, 0x02);
- let udp_repr = UdpRepr {
- src_port: 67,
- dst_port: 68,
- };
- #[cfg(feature = "proto-ipv6")]
- let ip_repr = IpRepr::Ipv6(Ipv6Repr {
- src_addr: src_ip,
- dst_addr: Ipv6Address::LINK_LOCAL_ALL_NODES,
- next_header: IpProtocol::Udp,
- payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
- hop_limit: 0x40,
- });
- #[cfg(all(not(feature = "proto-ipv6"), feature = "proto-ipv4"))]
- let ip_repr = IpRepr::Ipv4(Ipv4Repr {
- src_addr: src_ip,
- dst_addr: Ipv4Address::BROADCAST,
- next_header: IpProtocol::Udp,
- payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
- hop_limit: 0x40,
- });
- let dst_addr = ip_repr.dst_addr();
- // Bind the socket to port 68
- let socket = sockets.get_mut::<udp::Socket>(socket_handle);
- assert_eq!(socket.bind(68), Ok(()));
- assert!(!socket.can_recv());
- assert!(socket.can_send());
- udp_repr.emit(
- &mut packet,
- &ip_repr.src_addr(),
- &ip_repr.dst_addr(),
- UDP_PAYLOAD.len(),
- |buf| buf.copy_from_slice(&UDP_PAYLOAD),
- &ChecksumCapabilities::default(),
- );
- // Packet should be handled by bound UDP socket
- assert_eq!(
- iface.inner.process_udp(
- &mut sockets,
- PacketMeta::default(),
- false,
- ip_repr,
- packet.into_inner(),
- ),
- None
- );
- // Make sure the payload to the UDP packet processed by process_udp is
- // appended to the bound sockets rx_buffer
- let socket = sockets.get_mut::<udp::Socket>(socket_handle);
- assert!(socket.can_recv());
- assert_eq!(
- socket.recv(),
- Ok((
- &UDP_PAYLOAD[..],
- udp::UdpMetadata {
- local_address: Some(dst_addr),
- ..IpEndpoint::new(src_ip.into(), 67).into()
- }
- ))
- );
- }
- #[test]
- #[cfg(all(feature = "medium-ip", feature = "socket-tcp", feature = "proto-ipv6"))]
- pub fn tcp_not_accepted() {
- let (mut iface, mut sockets, _) = setup(Medium::Ip);
- let tcp = TcpRepr {
- src_port: 4242,
- dst_port: 4243,
- control: TcpControl::Syn,
- seq_number: TcpSeqNumber(-10001),
- ack_number: None,
- window_len: 256,
- window_scale: None,
- max_seg_size: None,
- sack_permitted: false,
- sack_ranges: [None, None, None],
- timestamp: None,
- payload: &[],
- };
- let mut tcp_bytes = vec![0u8; tcp.buffer_len()];
- tcp.emit(
- &mut TcpPacket::new_unchecked(&mut tcp_bytes),
- &Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2).into(),
- &Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1).into(),
- &ChecksumCapabilities::default(),
- );
- assert_eq!(
- iface.inner.process_tcp(
- &mut sockets,
- IpRepr::Ipv6(Ipv6Repr {
- src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2),
- dst_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
- next_header: IpProtocol::Tcp,
- payload_len: tcp.buffer_len(),
- hop_limit: 64,
- }),
- &tcp_bytes,
- ),
- Some(Packet::new_ipv6(
- Ipv6Repr {
- src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
- dst_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2),
- next_header: IpProtocol::Tcp,
- payload_len: tcp.buffer_len(),
- hop_limit: 64,
- },
- IpPayload::Tcp(TcpRepr {
- src_port: 4243,
- dst_port: 4242,
- control: TcpControl::Rst,
- seq_number: TcpSeqNumber(0),
- ack_number: Some(TcpSeqNumber(-10000)),
- window_len: 0,
- window_scale: None,
- max_seg_size: None,
- sack_permitted: false,
- sack_ranges: [None, None, None],
- timestamp: None,
- payload: &[],
- })
- ))
- );
- // Unspecified destination address.
- tcp.emit(
- &mut TcpPacket::new_unchecked(&mut tcp_bytes),
- &Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2).into(),
- &Ipv6Address::UNSPECIFIED.into(),
- &ChecksumCapabilities::default(),
- );
- assert_eq!(
- iface.inner.process_tcp(
- &mut sockets,
- IpRepr::Ipv6(Ipv6Repr {
- src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2),
- dst_addr: Ipv6Address::UNSPECIFIED,
- next_header: IpProtocol::Tcp,
- payload_len: tcp.buffer_len(),
- hop_limit: 64,
- }),
- &tcp_bytes,
- ),
- None,
- );
- }
|