1use core::cmp;
2#[cfg(feature = "async")]
3use core::task::Waker;
4
5use crate::phy::ChecksumCapabilities;
6#[cfg(feature = "async")]
7use crate::socket::WakerRegistration;
8use crate::socket::{Context, PollAt};
9
10use crate::storage::Empty;
11use crate::wire::IcmpRepr;
12#[cfg(feature = "proto-ipv4")]
13use crate::wire::{Icmpv4Packet, Icmpv4Repr, Ipv4Repr};
14#[cfg(feature = "proto-ipv6")]
15use crate::wire::{Icmpv6Packet, Icmpv6Repr, Ipv6Repr};
16use crate::wire::{IpAddress, IpListenEndpoint, IpProtocol, IpRepr};
17use crate::wire::{TcpPacket, TcpRepr};
18use crate::wire::{UdpPacket, UdpRepr};
19
20#[derive(Debug, PartialEq, Eq, Clone, Copy)]
22#[cfg_attr(feature = "defmt", derive(defmt::Format))]
23pub enum BindError {
24 InvalidState,
25 Unaddressable,
26}
27
28impl core::fmt::Display for BindError {
29 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
30 match self {
31 BindError::InvalidState => write!(f, "invalid state"),
32 BindError::Unaddressable => write!(f, "unaddressable"),
33 }
34 }
35}
36
37#[cfg(feature = "std")]
38impl std::error::Error for BindError {}
39
40#[derive(Debug, PartialEq, Eq, Clone, Copy)]
42#[cfg_attr(feature = "defmt", derive(defmt::Format))]
43pub enum SendError {
44 Unaddressable,
45 BufferFull,
46}
47
48impl core::fmt::Display for SendError {
49 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
50 match self {
51 SendError::Unaddressable => write!(f, "unaddressable"),
52 SendError::BufferFull => write!(f, "buffer full"),
53 }
54 }
55}
56
57#[cfg(feature = "std")]
58impl std::error::Error for SendError {}
59
60#[derive(Debug, PartialEq, Eq, Clone, Copy)]
62#[cfg_attr(feature = "defmt", derive(defmt::Format))]
63pub enum RecvError {
64 Exhausted,
65 Truncated,
66}
67
68impl core::fmt::Display for RecvError {
69 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
70 match self {
71 RecvError::Exhausted => write!(f, "exhausted"),
72 RecvError::Truncated => write!(f, "truncated"),
73 }
74 }
75}
76
77#[cfg(feature = "std")]
78impl std::error::Error for RecvError {}
79
80#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
85#[cfg_attr(feature = "defmt", derive(defmt::Format))]
86pub enum Endpoint {
87 #[default]
88 Unspecified,
89 Ident(u16),
90 Tcp(IpListenEndpoint),
91 Udp(IpListenEndpoint),
92}
93
94impl Endpoint {
95 pub fn is_specified(&self) -> bool {
96 match *self {
97 Endpoint::Unspecified => false,
98 Endpoint::Ident(_) => true,
99 Endpoint::Tcp(endpoint) => endpoint.port != 0,
100 Endpoint::Udp(endpoint) => endpoint.port != 0,
101 }
102 }
103}
104
105pub type PacketMetadata = crate::storage::PacketMetadata<IpAddress>;
107
108pub type PacketBuffer<'a> = crate::storage::PacketBuffer<'a, IpAddress>;
110
111#[derive(Debug)]
121pub struct Socket<'a> {
122 rx_buffer: PacketBuffer<'a>,
123 tx_buffer: PacketBuffer<'a>,
124 endpoint: Endpoint,
126 hop_limit: Option<u8>,
128 #[cfg(feature = "async")]
129 rx_waker: WakerRegistration,
130 #[cfg(feature = "async")]
131 tx_waker: WakerRegistration,
132}
133
134impl<'a> Socket<'a> {
135 pub fn new(rx_buffer: PacketBuffer<'a>, tx_buffer: PacketBuffer<'a>) -> Socket<'a> {
137 Socket {
138 rx_buffer,
139 tx_buffer,
140 endpoint: Default::default(),
141 hop_limit: None,
142 #[cfg(feature = "async")]
143 rx_waker: WakerRegistration::new(),
144 #[cfg(feature = "async")]
145 tx_waker: WakerRegistration::new(),
146 }
147 }
148
149 #[cfg(feature = "async")]
162 pub fn register_recv_waker(&mut self, waker: &Waker) {
163 self.rx_waker.register(waker)
164 }
165
166 #[cfg(feature = "async")]
180 pub fn register_send_waker(&mut self, waker: &Waker) {
181 self.tx_waker.register(waker)
182 }
183
184 pub fn hop_limit(&self) -> Option<u8> {
188 self.hop_limit
189 }
190
191 pub fn set_hop_limit(&mut self, hop_limit: Option<u8>) {
203 if let Some(0) = hop_limit {
205 panic!("the time-to-live value of a packet must not be zero")
206 }
207
208 self.hop_limit = hop_limit
209 }
210
211 pub fn bind<T: Into<Endpoint>>(&mut self, endpoint: T) -> Result<(), BindError> {
266 let endpoint = endpoint.into();
267 if !endpoint.is_specified() {
268 return Err(BindError::Unaddressable);
269 }
270
271 if self.is_open() {
272 return Err(BindError::InvalidState);
273 }
274
275 self.endpoint = endpoint;
276
277 #[cfg(feature = "async")]
278 {
279 self.rx_waker.wake();
280 self.tx_waker.wake();
281 }
282
283 Ok(())
284 }
285
286 #[inline]
288 pub fn can_send(&self) -> bool {
289 !self.tx_buffer.is_full()
290 }
291
292 #[inline]
294 pub fn can_recv(&self) -> bool {
295 !self.rx_buffer.is_empty()
296 }
297
298 #[inline]
300 pub fn packet_recv_capacity(&self) -> usize {
301 self.rx_buffer.packet_capacity()
302 }
303
304 #[inline]
306 pub fn packet_send_capacity(&self) -> usize {
307 self.tx_buffer.packet_capacity()
308 }
309
310 #[inline]
312 pub fn payload_recv_capacity(&self) -> usize {
313 self.rx_buffer.payload_capacity()
314 }
315
316 #[inline]
318 pub fn payload_send_capacity(&self) -> usize {
319 self.tx_buffer.payload_capacity()
320 }
321
322 #[inline]
324 pub fn is_open(&self) -> bool {
325 self.endpoint != Endpoint::Unspecified
326 }
327
328 pub fn send(&mut self, size: usize, endpoint: IpAddress) -> Result<&mut [u8], SendError> {
335 if endpoint.is_unspecified() {
336 return Err(SendError::Unaddressable);
337 }
338
339 let packet_buf = self
340 .tx_buffer
341 .enqueue(size, endpoint)
342 .map_err(|_| SendError::BufferFull)?;
343
344 net_trace!("icmp:{}: buffer to send {} octets", endpoint, size);
345 Ok(packet_buf)
346 }
347
348 pub fn send_with<F>(
354 &mut self,
355 max_size: usize,
356 endpoint: IpAddress,
357 f: F,
358 ) -> Result<usize, SendError>
359 where
360 F: FnOnce(&mut [u8]) -> usize,
361 {
362 if endpoint.is_unspecified() {
363 return Err(SendError::Unaddressable);
364 }
365
366 let size = self
367 .tx_buffer
368 .enqueue_with_infallible(max_size, endpoint, f)
369 .map_err(|_| SendError::BufferFull)?;
370
371 net_trace!("icmp:{}: buffer to send {} octets", endpoint, size);
372 Ok(size)
373 }
374
375 pub fn send_slice(&mut self, data: &[u8], endpoint: IpAddress) -> Result<(), SendError> {
379 let packet_buf = self.send(data.len(), endpoint)?;
380 packet_buf.copy_from_slice(data);
381 Ok(())
382 }
383
384 pub fn recv(&mut self) -> Result<(&[u8], IpAddress), RecvError> {
389 let (endpoint, packet_buf) = self.rx_buffer.dequeue().map_err(|_| RecvError::Exhausted)?;
390
391 net_trace!(
392 "icmp:{}: receive {} buffered octets",
393 endpoint,
394 packet_buf.len()
395 );
396 Ok((packet_buf, endpoint))
397 }
398
399 pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<(usize, IpAddress), RecvError> {
407 let (buffer, endpoint) = self.recv()?;
408
409 if data.len() < buffer.len() {
410 return Err(RecvError::Truncated);
411 }
412
413 let length = cmp::min(data.len(), buffer.len());
414 data[..length].copy_from_slice(&buffer[..length]);
415 Ok((length, endpoint))
416 }
417
418 pub fn send_queue(&self) -> usize {
420 self.tx_buffer.payload_bytes_count()
421 }
422
423 pub fn recv_queue(&self) -> usize {
425 self.rx_buffer.payload_bytes_count()
426 }
427
428 #[cfg(feature = "proto-ipv4")]
431 #[inline]
432 pub(crate) fn accepts_v4(
433 &self,
434 cx: &mut Context,
435 ip_repr: &Ipv4Repr,
436 icmp_repr: &Icmpv4Repr,
437 ) -> bool {
438 match (&self.endpoint, icmp_repr) {
439 (
444 &Endpoint::Udp(endpoint),
445 &Icmpv4Repr::DstUnreachable { data, header, .. }
446 | &Icmpv4Repr::TimeExceeded { data, header, .. },
447 ) if endpoint.addr.is_none() || endpoint.addr == Some(ip_repr.dst_addr.into()) => {
448 let packet = UdpPacket::new_unchecked(data);
449 match UdpRepr::parse(
450 &packet,
451 &header.src_addr.into(),
452 &header.dst_addr.into(),
453 &cx.checksum_caps(),
454 ) {
455 Ok(repr) => endpoint.port == repr.src_port,
456 Err(_) => false,
457 }
458 }
459 (
464 &Endpoint::Tcp(endpoint),
465 &Icmpv4Repr::DstUnreachable { data, header, .. }
466 | &Icmpv4Repr::TimeExceeded { data, header, .. },
467 ) if endpoint.addr.is_none() || endpoint.addr == Some(ip_repr.dst_addr.into()) => {
468 let packet = TcpPacket::new_unchecked(data);
469 match TcpRepr::parse(
470 &packet,
471 &header.src_addr.into(),
472 &header.dst_addr.into(),
473 &cx.checksum_caps(),
474 ) {
475 Ok(repr) => endpoint.port == repr.src_port,
476 Err(_) => false,
477 }
478 }
479 (&Endpoint::Ident(bound_ident), &Icmpv4Repr::EchoRequest { ident, .. })
483 | (&Endpoint::Ident(bound_ident), &Icmpv4Repr::EchoReply { ident, .. }) => {
484 ident == bound_ident
485 }
486 _ => false,
487 }
488 }
489
490 #[cfg(feature = "proto-ipv6")]
493 #[inline]
494 pub(crate) fn accepts_v6(
495 &self,
496 cx: &mut Context,
497 ip_repr: &Ipv6Repr,
498 icmp_repr: &Icmpv6Repr,
499 ) -> bool {
500 match (&self.endpoint, icmp_repr) {
501 (
506 &Endpoint::Udp(endpoint),
507 &Icmpv6Repr::DstUnreachable { data, header, .. }
508 | &Icmpv6Repr::TimeExceeded { data, header, .. },
509 ) if endpoint.addr.is_none() || endpoint.addr == Some(ip_repr.dst_addr.into()) => {
510 let packet = UdpPacket::new_unchecked(data);
511 match UdpRepr::parse(
512 &packet,
513 &header.src_addr.into(),
514 &header.dst_addr.into(),
515 &cx.checksum_caps(),
516 ) {
517 Ok(repr) => endpoint.port == repr.src_port,
518 Err(_) => false,
519 }
520 }
521 (
526 &Endpoint::Tcp(endpoint),
527 &Icmpv6Repr::DstUnreachable { data, header, .. }
528 | &Icmpv6Repr::TimeExceeded { data, header, .. },
529 ) if endpoint.addr.is_none() || endpoint.addr == Some(ip_repr.dst_addr.into()) => {
530 let packet = TcpPacket::new_unchecked(data);
531 match TcpRepr::parse(
532 &packet,
533 &header.src_addr.into(),
534 &header.dst_addr.into(),
535 &cx.checksum_caps(),
536 ) {
537 Ok(repr) => endpoint.port == repr.src_port,
538 Err(_) => false,
539 }
540 }
541 (
545 &Endpoint::Ident(bound_ident),
546 &Icmpv6Repr::EchoRequest { ident, .. } | &Icmpv6Repr::EchoReply { ident, .. },
547 ) => ident == bound_ident,
548 _ => false,
549 }
550 }
551
552 #[cfg(feature = "proto-ipv4")]
553 pub(crate) fn process_v4(
554 &mut self,
555 _cx: &mut Context,
556 ip_repr: &Ipv4Repr,
557 icmp_repr: &Icmpv4Repr,
558 ) {
559 net_trace!("icmp: receiving {} octets", icmp_repr.buffer_len());
560
561 match self
562 .rx_buffer
563 .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr.into())
564 {
565 Ok(packet_buf) => {
566 icmp_repr.emit(
567 &mut Icmpv4Packet::new_unchecked(packet_buf),
568 &ChecksumCapabilities::default(),
569 );
570 }
571 Err(_) => net_trace!("icmp: buffer full, dropped incoming packet"),
572 }
573
574 #[cfg(feature = "async")]
575 self.rx_waker.wake();
576 }
577
578 #[cfg(feature = "proto-ipv6")]
579 pub(crate) fn process_v6(
580 &mut self,
581 _cx: &mut Context,
582 ip_repr: &Ipv6Repr,
583 icmp_repr: &Icmpv6Repr,
584 ) {
585 net_trace!("icmp: receiving {} octets", icmp_repr.buffer_len());
586
587 match self
588 .rx_buffer
589 .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr.into())
590 {
591 Ok(packet_buf) => icmp_repr.emit(
592 &ip_repr.src_addr,
593 &ip_repr.dst_addr,
594 &mut Icmpv6Packet::new_unchecked(packet_buf),
595 &ChecksumCapabilities::default(),
596 ),
597 Err(_) => net_trace!("icmp: buffer full, dropped incoming packet"),
598 }
599
600 #[cfg(feature = "async")]
601 self.rx_waker.wake();
602 }
603
604 pub(crate) fn dispatch<F, E>(&mut self, cx: &mut Context, emit: F) -> Result<(), E>
605 where
606 F: FnOnce(&mut Context, (IpRepr, IcmpRepr)) -> Result<(), E>,
607 {
608 let hop_limit = self.hop_limit.unwrap_or(64);
609 let res = self.tx_buffer.dequeue_with(|remote_endpoint, packet_buf| {
610 net_trace!(
611 "icmp:{}: sending {} octets",
612 remote_endpoint,
613 packet_buf.len()
614 );
615 match *remote_endpoint {
616 #[cfg(feature = "proto-ipv4")]
617 IpAddress::Ipv4(dst_addr) => {
618 let src_addr = match cx.get_source_address_ipv4(&dst_addr) {
619 Some(addr) => addr,
620 None => {
621 net_trace!(
622 "icmp:{}: not find suitable source address, dropping",
623 remote_endpoint
624 );
625 return Ok(());
626 }
627 };
628 let packet = Icmpv4Packet::new_unchecked(&*packet_buf);
629 let repr = match Icmpv4Repr::parse(&packet, &ChecksumCapabilities::ignored()) {
630 Ok(x) => x,
631 Err(_) => {
632 net_trace!(
633 "icmp:{}: malformed packet in queue, dropping",
634 remote_endpoint
635 );
636 return Ok(());
637 }
638 };
639 let ip_repr = IpRepr::Ipv4(Ipv4Repr {
640 src_addr,
641 dst_addr,
642 next_header: IpProtocol::Icmp,
643 payload_len: repr.buffer_len(),
644 hop_limit,
645 });
646 emit(cx, (ip_repr, IcmpRepr::Ipv4(repr)))
647 }
648 #[cfg(feature = "proto-ipv6")]
649 IpAddress::Ipv6(dst_addr) => {
650 let src_addr = cx.get_source_address_ipv6(&dst_addr);
651
652 let packet = Icmpv6Packet::new_unchecked(&*packet_buf);
653 let repr = match Icmpv6Repr::parse(
654 &src_addr,
655 &dst_addr,
656 &packet,
657 &ChecksumCapabilities::ignored(),
658 ) {
659 Ok(x) => x,
660 Err(_) => {
661 net_trace!(
662 "icmp:{}: malformed packet in queue, dropping",
663 remote_endpoint
664 );
665 return Ok(());
666 }
667 };
668 let ip_repr = IpRepr::Ipv6(Ipv6Repr {
669 src_addr,
670 dst_addr,
671 next_header: IpProtocol::Icmpv6,
672 payload_len: repr.buffer_len(),
673 hop_limit,
674 });
675 emit(cx, (ip_repr, IcmpRepr::Ipv6(repr)))
676 }
677 }
678 });
679 match res {
680 Err(Empty) => Ok(()),
681 Ok(Err(e)) => Err(e),
682 Ok(Ok(())) => {
683 #[cfg(feature = "async")]
684 self.tx_waker.wake();
685 Ok(())
686 }
687 }
688 }
689
690 pub(crate) fn poll_at(&self, _cx: &mut Context) -> PollAt {
691 if self.tx_buffer.is_empty() {
692 PollAt::Ingress
693 } else {
694 PollAt::Now
695 }
696 }
697}
698
699#[cfg(test)]
700mod tests_common {
701 pub use super::*;
702 pub use crate::wire::IpAddress;
703
704 pub fn buffer(packets: usize) -> PacketBuffer<'static> {
705 PacketBuffer::new(vec![PacketMetadata::EMPTY; packets], vec![0; 66 * packets])
706 }
707
708 pub fn socket(
709 rx_buffer: PacketBuffer<'static>,
710 tx_buffer: PacketBuffer<'static>,
711 ) -> Socket<'static> {
712 Socket::new(rx_buffer, tx_buffer)
713 }
714
715 pub const LOCAL_PORT: u16 = 53;
716
717 pub static UDP_REPR: UdpRepr = UdpRepr {
718 src_port: 53,
719 dst_port: 9090,
720 };
721
722 pub static UDP_PAYLOAD: &[u8] = &[0xff; 10];
723}
724
725#[cfg(all(test, feature = "proto-ipv4"))]
726mod test_ipv4 {
727 use crate::phy::Medium;
728 use crate::tests::setup;
729 use rstest::*;
730
731 use super::tests_common::*;
732 use crate::wire::{Icmpv4DstUnreachable, IpEndpoint, Ipv4Address};
733
734 const REMOTE_IPV4: Ipv4Address = Ipv4Address::new(192, 168, 1, 2);
735 const LOCAL_IPV4: Ipv4Address = Ipv4Address::new(192, 168, 1, 1);
736 const LOCAL_END_V4: IpEndpoint = IpEndpoint {
737 addr: IpAddress::Ipv4(LOCAL_IPV4),
738 port: LOCAL_PORT,
739 };
740
741 static ECHOV4_REPR: Icmpv4Repr = Icmpv4Repr::EchoRequest {
742 ident: 0x1234,
743 seq_no: 0x5678,
744 data: &[0xff; 16],
745 };
746
747 static LOCAL_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr {
748 src_addr: LOCAL_IPV4,
749 dst_addr: REMOTE_IPV4,
750 next_header: IpProtocol::Icmp,
751 payload_len: 24,
752 hop_limit: 0x40,
753 });
754
755 static REMOTE_IPV4_REPR: Ipv4Repr = Ipv4Repr {
756 src_addr: REMOTE_IPV4,
757 dst_addr: LOCAL_IPV4,
758 next_header: IpProtocol::Icmp,
759 payload_len: 24,
760 hop_limit: 0x40,
761 };
762
763 #[test]
764 fn test_send_unaddressable() {
765 let mut socket = socket(buffer(0), buffer(1));
766 assert_eq!(
767 socket.send_slice(b"abcdef", IpAddress::Ipv4(Ipv4Address::new(0, 0, 0, 0))),
768 Err(SendError::Unaddressable)
769 );
770 assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV4.into()), Ok(()));
771 }
772
773 #[rstest]
774 #[case::ethernet(Medium::Ethernet)]
775 #[cfg(feature = "medium-ethernet")]
776 fn test_send_dispatch(#[case] medium: Medium) {
777 let (mut iface, _, _) = setup(medium);
778 let cx = iface.context();
779
780 let mut socket = socket(buffer(0), buffer(1));
781 let checksum = ChecksumCapabilities::default();
782
783 assert_eq!(socket.dispatch(cx, |_, _| unreachable!()), Ok::<_, ()>(()));
784
785 assert_eq!(
787 socket.send_slice(&[0xff; 67], REMOTE_IPV4.into()),
788 Err(SendError::BufferFull)
789 );
790 assert!(socket.can_send());
791
792 let mut bytes = [0xff; 24];
793 let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
794 ECHOV4_REPR.emit(&mut packet, &checksum);
795
796 assert_eq!(
797 socket.send_slice(&*packet.into_inner(), REMOTE_IPV4.into()),
798 Ok(())
799 );
800 assert_eq!(
801 socket.send_slice(b"123456", REMOTE_IPV4.into()),
802 Err(SendError::BufferFull)
803 );
804 assert!(!socket.can_send());
805
806 assert_eq!(
807 socket.dispatch(cx, |_, (ip_repr, icmp_repr)| {
808 assert_eq!(ip_repr, LOCAL_IPV4_REPR);
809 assert_eq!(icmp_repr, ECHOV4_REPR.into());
810 Err(())
811 }),
812 Err(())
813 );
814 assert!(!socket.can_send());
816
817 assert_eq!(
818 socket.dispatch(cx, |_, (ip_repr, icmp_repr)| {
819 assert_eq!(ip_repr, LOCAL_IPV4_REPR);
820 assert_eq!(icmp_repr, ECHOV4_REPR.into());
821 Ok::<_, ()>(())
822 }),
823 Ok(())
824 );
825 assert!(socket.can_send());
827 }
828
829 #[rstest]
830 #[case::ethernet(Medium::Ethernet)]
831 #[cfg(feature = "medium-ethernet")]
832 fn test_set_hop_limit_v4(#[case] medium: Medium) {
833 let (mut iface, _, _) = setup(medium);
834 let cx = iface.context();
835
836 let mut s = socket(buffer(0), buffer(1));
837 let checksum = ChecksumCapabilities::default();
838
839 let mut bytes = [0xff; 24];
840 let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
841 ECHOV4_REPR.emit(&mut packet, &checksum);
842
843 s.set_hop_limit(Some(0x2a));
844
845 assert_eq!(
846 s.send_slice(&*packet.into_inner(), REMOTE_IPV4.into()),
847 Ok(())
848 );
849 assert_eq!(
850 s.dispatch(cx, |_, (ip_repr, _)| {
851 assert_eq!(
852 ip_repr,
853 IpRepr::Ipv4(Ipv4Repr {
854 src_addr: LOCAL_IPV4,
855 dst_addr: REMOTE_IPV4,
856 next_header: IpProtocol::Icmp,
857 payload_len: ECHOV4_REPR.buffer_len(),
858 hop_limit: 0x2a,
859 })
860 );
861 Ok::<_, ()>(())
862 }),
863 Ok(())
864 );
865 }
866
867 #[rstest]
868 #[case::ethernet(Medium::Ethernet)]
869 #[cfg(feature = "medium-ethernet")]
870 fn test_recv_process(#[case] medium: Medium) {
871 let (mut iface, _, _) = setup(medium);
872 let cx = iface.context();
873
874 let mut socket = socket(buffer(1), buffer(1));
875 assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
876
877 assert!(!socket.can_recv());
878 assert_eq!(socket.recv(), Err(RecvError::Exhausted));
879
880 let checksum = ChecksumCapabilities::default();
881
882 let mut bytes = [0xff; 24];
883 let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]);
884 ECHOV4_REPR.emit(&mut packet, &checksum);
885 let data = &*packet.into_inner();
886
887 assert!(socket.accepts_v4(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR));
888 socket.process_v4(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR);
889 assert!(socket.can_recv());
890
891 assert!(socket.accepts_v4(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR));
892 socket.process_v4(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR);
893
894 assert_eq!(socket.recv(), Ok((data, REMOTE_IPV4.into())));
895 assert!(!socket.can_recv());
896 }
897
898 #[rstest]
899 #[case::ethernet(Medium::Ethernet)]
900 #[cfg(feature = "medium-ethernet")]
901 fn test_accept_bad_id(#[case] medium: Medium) {
902 let (mut iface, _, _) = setup(medium);
903 let cx = iface.context();
904
905 let mut socket = socket(buffer(1), buffer(1));
906 assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
907
908 let checksum = ChecksumCapabilities::default();
909 let mut bytes = [0xff; 20];
910 let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
911 let icmp_repr = Icmpv4Repr::EchoRequest {
912 ident: 0x4321,
913 seq_no: 0x5678,
914 data: &[0xff; 16],
915 };
916 icmp_repr.emit(&mut packet, &checksum);
917
918 assert!(!socket.accepts_v4(cx, &REMOTE_IPV4_REPR, &icmp_repr));
921 }
922
923 #[rstest]
924 #[case::ethernet(Medium::Ethernet)]
925 #[cfg(feature = "medium-ethernet")]
926 fn test_accepts_udp(#[case] medium: Medium) {
927 let (mut iface, _, _) = setup(medium);
928 let cx = iface.context();
929
930 let mut socket = socket(buffer(1), buffer(1));
931 assert_eq!(socket.bind(Endpoint::Udp(LOCAL_END_V4.into())), Ok(()));
932
933 let checksum = ChecksumCapabilities::default();
934
935 let mut bytes = [0xff; 18];
936 let mut packet = UdpPacket::new_unchecked(&mut bytes);
937 UDP_REPR.emit(
938 &mut packet,
939 &REMOTE_IPV4.into(),
940 &LOCAL_IPV4.into(),
941 UDP_PAYLOAD.len(),
942 |buf| buf.copy_from_slice(UDP_PAYLOAD),
943 &checksum,
944 );
945
946 let data = &*packet.into_inner();
947
948 let icmp_repr = Icmpv4Repr::DstUnreachable {
949 reason: Icmpv4DstUnreachable::PortUnreachable,
950 header: Ipv4Repr {
951 src_addr: LOCAL_IPV4,
952 dst_addr: REMOTE_IPV4,
953 next_header: IpProtocol::Icmp,
954 payload_len: 12,
955 hop_limit: 0x40,
956 },
957 data,
958 };
959 let ip_repr = Ipv4Repr {
960 src_addr: REMOTE_IPV4,
961 dst_addr: LOCAL_IPV4,
962 next_header: IpProtocol::Icmp,
963 payload_len: icmp_repr.buffer_len(),
964 hop_limit: 0x40,
965 };
966
967 assert!(!socket.can_recv());
968
969 assert!(socket.accepts_v4(cx, &ip_repr, &icmp_repr));
972 socket.process_v4(cx, &ip_repr, &icmp_repr);
973 assert!(socket.can_recv());
974
975 let mut bytes = [0x00; 46];
976 let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]);
977 icmp_repr.emit(&mut packet, &checksum);
978 assert_eq!(
979 socket.recv(),
980 Ok((&*packet.into_inner(), REMOTE_IPV4.into()))
981 );
982 assert!(!socket.can_recv());
983 }
984}
985
986#[cfg(all(test, feature = "proto-ipv6"))]
987mod test_ipv6 {
988 use crate::phy::Medium;
989 use crate::tests::setup;
990 use rstest::*;
991
992 use super::tests_common::*;
993
994 use crate::wire::{Icmpv6DstUnreachable, IpEndpoint, Ipv6Address};
995
996 const REMOTE_IPV6: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2);
997 const LOCAL_IPV6: Ipv6Address = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
998 const LOCAL_END_V6: IpEndpoint = IpEndpoint {
999 addr: IpAddress::Ipv6(LOCAL_IPV6),
1000 port: LOCAL_PORT,
1001 };
1002 static ECHOV6_REPR: Icmpv6Repr = Icmpv6Repr::EchoRequest {
1003 ident: 0x1234,
1004 seq_no: 0x5678,
1005 data: &[0xff; 16],
1006 };
1007
1008 static LOCAL_IPV6_REPR: Ipv6Repr = Ipv6Repr {
1009 src_addr: LOCAL_IPV6,
1010 dst_addr: REMOTE_IPV6,
1011 next_header: IpProtocol::Icmpv6,
1012 payload_len: 24,
1013 hop_limit: 0x40,
1014 };
1015
1016 static REMOTE_IPV6_REPR: Ipv6Repr = Ipv6Repr {
1017 src_addr: REMOTE_IPV6,
1018 dst_addr: LOCAL_IPV6,
1019 next_header: IpProtocol::Icmpv6,
1020 payload_len: 24,
1021 hop_limit: 0x40,
1022 };
1023
1024 #[test]
1025 fn test_send_unaddressable() {
1026 let mut socket = socket(buffer(0), buffer(1));
1027 assert_eq!(
1028 socket.send_slice(b"abcdef", IpAddress::Ipv6(Ipv6Address::UNSPECIFIED)),
1029 Err(SendError::Unaddressable)
1030 );
1031 assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV6.into()), Ok(()));
1032 }
1033
1034 #[rstest]
1035 #[case::ethernet(Medium::Ethernet)]
1036 #[cfg(feature = "medium-ethernet")]
1037 fn test_send_dispatch(#[case] medium: Medium) {
1038 let (mut iface, _, _) = setup(medium);
1039 let cx = iface.context();
1040
1041 let mut socket = socket(buffer(0), buffer(1));
1042 let checksum = ChecksumCapabilities::default();
1043
1044 assert_eq!(socket.dispatch(cx, |_, _| unreachable!()), Ok::<_, ()>(()));
1045
1046 assert_eq!(
1048 socket.send_slice(&[0xff; 67], REMOTE_IPV6.into()),
1049 Err(SendError::BufferFull)
1050 );
1051 assert!(socket.can_send());
1052
1053 let mut bytes = vec![0xff; 24];
1054 let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
1055 ECHOV6_REPR.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
1056
1057 assert_eq!(
1058 socket.send_slice(&*packet.into_inner(), REMOTE_IPV6.into()),
1059 Ok(())
1060 );
1061 assert_eq!(
1062 socket.send_slice(b"123456", REMOTE_IPV6.into()),
1063 Err(SendError::BufferFull)
1064 );
1065 assert!(!socket.can_send());
1066
1067 assert_eq!(
1068 socket.dispatch(cx, |_, (ip_repr, icmp_repr)| {
1069 assert_eq!(ip_repr, LOCAL_IPV6_REPR.into());
1070 assert_eq!(icmp_repr, ECHOV6_REPR.into());
1071 Err(())
1072 }),
1073 Err(())
1074 );
1075 assert!(!socket.can_send());
1077
1078 assert_eq!(
1079 socket.dispatch(cx, |_, (ip_repr, icmp_repr)| {
1080 assert_eq!(ip_repr, LOCAL_IPV6_REPR.into());
1081 assert_eq!(icmp_repr, ECHOV6_REPR.into());
1082 Ok::<_, ()>(())
1083 }),
1084 Ok(())
1085 );
1086 assert!(socket.can_send());
1088 }
1089
1090 #[rstest]
1091 #[case::ethernet(Medium::Ethernet)]
1092 #[cfg(feature = "medium-ethernet")]
1093 fn test_set_hop_limit(#[case] medium: Medium) {
1094 let (mut iface, _, _) = setup(medium);
1095 let cx = iface.context();
1096
1097 let mut s = socket(buffer(0), buffer(1));
1098 let checksum = ChecksumCapabilities::default();
1099
1100 let mut bytes = vec![0xff; 24];
1101 let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
1102 ECHOV6_REPR.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
1103
1104 s.set_hop_limit(Some(0x2a));
1105
1106 assert_eq!(
1107 s.send_slice(&*packet.into_inner(), REMOTE_IPV6.into()),
1108 Ok(())
1109 );
1110 assert_eq!(
1111 s.dispatch(cx, |_, (ip_repr, _)| {
1112 assert_eq!(
1113 ip_repr,
1114 IpRepr::Ipv6(Ipv6Repr {
1115 src_addr: LOCAL_IPV6,
1116 dst_addr: REMOTE_IPV6,
1117 next_header: IpProtocol::Icmpv6,
1118 payload_len: ECHOV6_REPR.buffer_len(),
1119 hop_limit: 0x2a,
1120 })
1121 );
1122 Ok::<_, ()>(())
1123 }),
1124 Ok(())
1125 );
1126 }
1127
1128 #[rstest]
1129 #[case::ethernet(Medium::Ethernet)]
1130 #[cfg(feature = "medium-ethernet")]
1131 fn test_recv_process(#[case] medium: Medium) {
1132 let (mut iface, _, _) = setup(medium);
1133 let cx = iface.context();
1134
1135 let mut socket = socket(buffer(1), buffer(1));
1136 assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
1137
1138 assert!(!socket.can_recv());
1139 assert_eq!(socket.recv(), Err(RecvError::Exhausted));
1140
1141 let checksum = ChecksumCapabilities::default();
1142
1143 let mut bytes = [0xff; 24];
1144 let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]);
1145 ECHOV6_REPR.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
1146 let data = &*packet.into_inner();
1147
1148 assert!(socket.accepts_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR));
1149 socket.process_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR);
1150 assert!(socket.can_recv());
1151
1152 assert!(socket.accepts_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR));
1153 socket.process_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR);
1154
1155 assert_eq!(socket.recv(), Ok((data, REMOTE_IPV6.into())));
1156 assert!(!socket.can_recv());
1157 }
1158
1159 #[rstest]
1160 #[case::ethernet(Medium::Ethernet)]
1161 #[cfg(feature = "medium-ethernet")]
1162 fn test_truncated_recv_slice(#[case] medium: Medium) {
1163 let (mut iface, _, _) = setup(medium);
1164 let cx = iface.context();
1165
1166 let mut socket = socket(buffer(1), buffer(1));
1167 assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
1168
1169 let checksum = ChecksumCapabilities::default();
1170
1171 let mut bytes = [0xff; 24];
1172 let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]);
1173 ECHOV6_REPR.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
1174
1175 assert!(socket.accepts_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR));
1176 socket.process_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR);
1177 assert!(socket.can_recv());
1178
1179 assert!(socket.accepts_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR));
1180 socket.process_v6(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR);
1181
1182 let mut buffer = [0u8; 1];
1183 assert_eq!(
1184 socket.recv_slice(&mut buffer[..]),
1185 Err(RecvError::Truncated)
1186 );
1187 assert!(!socket.can_recv());
1188 }
1189
1190 #[rstest]
1191 #[case::ethernet(Medium::Ethernet)]
1192 #[cfg(feature = "medium-ethernet")]
1193 fn test_accept_bad_id(#[case] medium: Medium) {
1194 let (mut iface, _, _) = setup(medium);
1195 let cx = iface.context();
1196
1197 let mut socket = socket(buffer(1), buffer(1));
1198 assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
1199
1200 let checksum = ChecksumCapabilities::default();
1201 let mut bytes = [0xff; 20];
1202 let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
1203 let icmp_repr = Icmpv6Repr::EchoRequest {
1204 ident: 0x4321,
1205 seq_no: 0x5678,
1206 data: &[0xff; 16],
1207 };
1208 icmp_repr.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
1209
1210 assert!(!socket.accepts_v6(cx, &REMOTE_IPV6_REPR, &icmp_repr));
1213 }
1214
1215 #[rstest]
1216 #[case::ethernet(Medium::Ethernet)]
1217 #[cfg(feature = "medium-ethernet")]
1218 fn test_accepts_udp(#[case] medium: Medium) {
1219 let (mut iface, _, _) = setup(medium);
1220 let cx = iface.context();
1221
1222 let mut socket = socket(buffer(1), buffer(1));
1223 assert_eq!(socket.bind(Endpoint::Udp(LOCAL_END_V6.into())), Ok(()));
1224
1225 let checksum = ChecksumCapabilities::default();
1226
1227 let mut bytes = [0xff; 18];
1228 let mut packet = UdpPacket::new_unchecked(&mut bytes);
1229 UDP_REPR.emit(
1230 &mut packet,
1231 &REMOTE_IPV6.into(),
1232 &LOCAL_IPV6.into(),
1233 UDP_PAYLOAD.len(),
1234 |buf| buf.copy_from_slice(UDP_PAYLOAD),
1235 &checksum,
1236 );
1237
1238 let data = &*packet.into_inner();
1239
1240 let icmp_repr = Icmpv6Repr::DstUnreachable {
1241 reason: Icmpv6DstUnreachable::PortUnreachable,
1242 header: Ipv6Repr {
1243 src_addr: LOCAL_IPV6,
1244 dst_addr: REMOTE_IPV6,
1245 next_header: IpProtocol::Icmpv6,
1246 payload_len: 12,
1247 hop_limit: 0x40,
1248 },
1249 data,
1250 };
1251 let ip_repr = Ipv6Repr {
1252 src_addr: REMOTE_IPV6,
1253 dst_addr: LOCAL_IPV6,
1254 next_header: IpProtocol::Icmpv6,
1255 payload_len: icmp_repr.buffer_len(),
1256 hop_limit: 0x40,
1257 };
1258
1259 assert!(!socket.can_recv());
1260
1261 assert!(socket.accepts_v6(cx, &ip_repr, &icmp_repr));
1264 socket.process_v6(cx, &ip_repr, &icmp_repr);
1265 assert!(socket.can_recv());
1266
1267 let mut bytes = [0x00; 66];
1268 let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]);
1269 icmp_repr.emit(&LOCAL_IPV6, &REMOTE_IPV6, &mut packet, &checksum);
1270 assert_eq!(
1271 socket.recv(),
1272 Ok((&*packet.into_inner(), REMOTE_IPV6.into()))
1273 );
1274 assert!(!socket.can_recv());
1275 }
1276}