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};
9use crate::storage::{PacketBuffer, PacketMetadata};
10use crate::{Error, Result};
11
12use crate::wire::IcmpRepr;
13#[cfg(feature = "proto-ipv4")]
14use crate::wire::{Icmpv4Packet, Icmpv4Repr, Ipv4Address, Ipv4Repr};
15#[cfg(feature = "proto-ipv6")]
16use crate::wire::{Icmpv6Packet, Icmpv6Repr, Ipv6Address, Ipv6Repr};
17use crate::wire::{IpAddress, IpEndpoint, IpProtocol, IpRepr};
18use crate::wire::{UdpPacket, UdpRepr};
19
20#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26pub enum Endpoint {
27 Unspecified,
28 Ident(u16),
29 Udp(IpEndpoint),
30}
31
32impl Endpoint {
33 pub fn is_specified(&self) -> bool {
34 match *self {
35 Endpoint::Ident(_) => true,
36 Endpoint::Udp(endpoint) => endpoint.port != 0,
37 Endpoint::Unspecified => false,
38 }
39 }
40}
41
42impl Default for Endpoint {
43 fn default() -> Endpoint {
44 Endpoint::Unspecified
45 }
46}
47
48pub type IcmpPacketMetadata = PacketMetadata<IpAddress>;
50
51pub type IcmpSocketBuffer<'a> = PacketBuffer<'a, IpAddress>;
53
54#[derive(Debug)]
64pub struct IcmpSocket<'a> {
65 rx_buffer: IcmpSocketBuffer<'a>,
66 tx_buffer: IcmpSocketBuffer<'a>,
67 endpoint: Endpoint,
69 hop_limit: Option<u8>,
71 #[cfg(feature = "async")]
72 rx_waker: WakerRegistration,
73 #[cfg(feature = "async")]
74 tx_waker: WakerRegistration,
75}
76
77impl<'a> IcmpSocket<'a> {
78 pub fn new(rx_buffer: IcmpSocketBuffer<'a>, tx_buffer: IcmpSocketBuffer<'a>) -> IcmpSocket<'a> {
80 IcmpSocket {
81 rx_buffer: rx_buffer,
82 tx_buffer: tx_buffer,
83 endpoint: Endpoint::default(),
84 hop_limit: None,
85 #[cfg(feature = "async")]
86 rx_waker: WakerRegistration::new(),
87 #[cfg(feature = "async")]
88 tx_waker: WakerRegistration::new(),
89 }
90 }
91
92 #[cfg(feature = "async")]
105 pub fn register_recv_waker(&mut self, waker: &Waker) {
106 self.rx_waker.register(waker)
107 }
108
109 #[cfg(feature = "async")]
123 pub fn register_send_waker(&mut self, waker: &Waker) {
124 self.tx_waker.register(waker)
125 }
126
127 pub fn hop_limit(&self) -> Option<u8> {
131 self.hop_limit
132 }
133
134 pub fn set_hop_limit(&mut self, hop_limit: Option<u8>) {
146 if let Some(0) = hop_limit {
148 panic!("the time-to-live value of a packet must not be zero")
149 }
150
151 self.hop_limit = hop_limit
152 }
153
154 pub fn bind<T: Into<Endpoint>>(&mut self, endpoint: T) -> Result<()> {
210 let endpoint = endpoint.into();
211 if !endpoint.is_specified() {
212 return Err(Error::Unaddressable);
213 }
214
215 if self.is_open() {
216 return Err(Error::Illegal);
217 }
218
219 self.endpoint = endpoint;
220
221 #[cfg(feature = "async")]
222 {
223 self.rx_waker.wake();
224 self.tx_waker.wake();
225 }
226
227 Ok(())
228 }
229
230 #[inline]
232 pub fn can_send(&self) -> bool {
233 !self.tx_buffer.is_full()
234 }
235
236 #[inline]
238 pub fn can_recv(&self) -> bool {
239 !self.rx_buffer.is_empty()
240 }
241
242 #[inline]
244 pub fn packet_recv_capacity(&self) -> usize {
245 self.rx_buffer.packet_capacity()
246 }
247
248 #[inline]
250 pub fn packet_send_capacity(&self) -> usize {
251 self.tx_buffer.packet_capacity()
252 }
253
254 #[inline]
256 pub fn payload_recv_capacity(&self) -> usize {
257 self.rx_buffer.payload_capacity()
258 }
259
260 #[inline]
262 pub fn payload_send_capacity(&self) -> usize {
263 self.tx_buffer.payload_capacity()
264 }
265
266 #[inline]
268 pub fn is_open(&self) -> bool {
269 self.endpoint != Endpoint::Unspecified
270 }
271
272 pub fn send(&mut self, size: usize, endpoint: IpAddress) -> Result<&mut [u8]> {
279 if endpoint.is_unspecified() {
280 return Err(Error::Unaddressable);
281 }
282
283 let packet_buf = self.tx_buffer.enqueue(size, endpoint)?;
284
285 net_trace!("icmp:{}: buffer to send {} octets", endpoint, size);
286 Ok(packet_buf)
287 }
288
289 pub fn send_slice(&mut self, data: &[u8], endpoint: IpAddress) -> Result<()> {
293 let packet_buf = self.send(data.len(), endpoint)?;
294 packet_buf.copy_from_slice(data);
295 Ok(())
296 }
297
298 pub fn recv(&mut self) -> Result<(&[u8], IpAddress)> {
303 let (endpoint, packet_buf) = self.rx_buffer.dequeue()?;
304
305 net_trace!(
306 "icmp:{}: receive {} buffered octets",
307 endpoint,
308 packet_buf.len()
309 );
310 Ok((packet_buf, endpoint))
311 }
312
313 pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<(usize, IpAddress)> {
318 let (buffer, endpoint) = self.recv()?;
319 let length = cmp::min(data.len(), buffer.len());
320 data[..length].copy_from_slice(&buffer[..length]);
321 Ok((length, endpoint))
322 }
323
324 pub(crate) fn accepts(&self, cx: &mut Context, ip_repr: &IpRepr, icmp_repr: &IcmpRepr) -> bool {
327 match (&self.endpoint, icmp_repr) {
328 #[cfg(feature = "proto-ipv4")]
332 (
333 &Endpoint::Udp(endpoint),
334 &IcmpRepr::Ipv4(Icmpv4Repr::DstUnreachable { data, .. }),
335 ) if endpoint.addr.is_unspecified() || endpoint.addr == ip_repr.dst_addr() => {
336 let packet = UdpPacket::new_unchecked(data);
337 match UdpRepr::parse(
338 &packet,
339 &ip_repr.src_addr(),
340 &ip_repr.dst_addr(),
341 &cx.checksum_caps(),
342 ) {
343 Ok(repr) => endpoint.port == repr.src_port,
344 Err(_) => false,
345 }
346 }
347 #[cfg(feature = "proto-ipv6")]
348 (
349 &Endpoint::Udp(endpoint),
350 &IcmpRepr::Ipv6(Icmpv6Repr::DstUnreachable { data, .. }),
351 ) if endpoint.addr.is_unspecified() || endpoint.addr == ip_repr.dst_addr() => {
352 let packet = UdpPacket::new_unchecked(data);
353 match UdpRepr::parse(
354 &packet,
355 &ip_repr.src_addr(),
356 &ip_repr.dst_addr(),
357 &cx.checksum_caps(),
358 ) {
359 Ok(repr) => endpoint.port == repr.src_port,
360 Err(_) => false,
361 }
362 }
363 #[cfg(feature = "proto-ipv4")]
367 (
368 &Endpoint::Ident(bound_ident),
369 &IcmpRepr::Ipv4(Icmpv4Repr::EchoRequest { ident, .. }),
370 )
371 | (
372 &Endpoint::Ident(bound_ident),
373 &IcmpRepr::Ipv4(Icmpv4Repr::EchoReply { ident, .. }),
374 ) => ident == bound_ident,
375 #[cfg(feature = "proto-ipv6")]
376 (
377 &Endpoint::Ident(bound_ident),
378 &IcmpRepr::Ipv6(Icmpv6Repr::EchoRequest { ident, .. }),
379 )
380 | (
381 &Endpoint::Ident(bound_ident),
382 &IcmpRepr::Ipv6(Icmpv6Repr::EchoReply { ident, .. }),
383 ) => ident == bound_ident,
384 _ => false,
385 }
386 }
387
388 pub(crate) fn process(
389 &mut self,
390 _cx: &mut Context,
391 ip_repr: &IpRepr,
392 icmp_repr: &IcmpRepr,
393 ) -> Result<()> {
394 match *icmp_repr {
395 #[cfg(feature = "proto-ipv4")]
396 IcmpRepr::Ipv4(ref icmp_repr) => {
397 let packet_buf = self
398 .rx_buffer
399 .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())?;
400 icmp_repr.emit(
401 &mut Icmpv4Packet::new_unchecked(packet_buf),
402 &ChecksumCapabilities::default(),
403 );
404
405 net_trace!(
406 "icmp:{}: receiving {} octets",
407 icmp_repr.buffer_len(),
408 packet_buf.len()
409 );
410 }
411 #[cfg(feature = "proto-ipv6")]
412 IcmpRepr::Ipv6(ref icmp_repr) => {
413 let packet_buf = self
414 .rx_buffer
415 .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())?;
416 icmp_repr.emit(
417 &ip_repr.src_addr(),
418 &ip_repr.dst_addr(),
419 &mut Icmpv6Packet::new_unchecked(packet_buf),
420 &ChecksumCapabilities::default(),
421 );
422
423 net_trace!(
424 "icmp:{}: receiving {} octets",
425 icmp_repr.buffer_len(),
426 packet_buf.len()
427 );
428 }
429 }
430
431 #[cfg(feature = "async")]
432 self.rx_waker.wake();
433
434 Ok(())
435 }
436
437 pub(crate) fn dispatch<F>(&mut self, cx: &mut Context, emit: F) -> Result<()>
438 where
439 F: FnOnce(&mut Context, (IpRepr, IcmpRepr)) -> Result<()>,
440 {
441 let hop_limit = self.hop_limit.unwrap_or(64);
442 self.tx_buffer.dequeue_with(|remote_endpoint, packet_buf| {
443 net_trace!(
444 "icmp:{}: sending {} octets",
445 remote_endpoint,
446 packet_buf.len()
447 );
448 match *remote_endpoint {
449 #[cfg(feature = "proto-ipv4")]
450 IpAddress::Ipv4(ipv4_addr) => {
451 let packet = Icmpv4Packet::new_unchecked(&*packet_buf);
452 let repr = Icmpv4Repr::parse(&packet, &ChecksumCapabilities::ignored())?;
453 let ip_repr = IpRepr::Ipv4(Ipv4Repr {
454 src_addr: Ipv4Address::default(),
455 dst_addr: ipv4_addr,
456 protocol: IpProtocol::Icmp,
457 payload_len: repr.buffer_len(),
458 hop_limit: hop_limit,
459 });
460 emit(cx, (ip_repr, IcmpRepr::Ipv4(repr)))
461 }
462 #[cfg(feature = "proto-ipv6")]
463 IpAddress::Ipv6(ipv6_addr) => {
464 let packet = Icmpv6Packet::new_unchecked(&*packet_buf);
465 let src_addr = Ipv6Address::default();
466 let repr = Icmpv6Repr::parse(
467 &src_addr.into(),
468 &ipv6_addr.into(),
469 &packet,
470 &ChecksumCapabilities::ignored(),
471 )?;
472 let ip_repr = IpRepr::Ipv6(Ipv6Repr {
473 src_addr: src_addr,
474 dst_addr: ipv6_addr,
475 next_header: IpProtocol::Icmpv6,
476 payload_len: repr.buffer_len(),
477 hop_limit: hop_limit,
478 });
479 emit(cx, (ip_repr, IcmpRepr::Ipv6(repr)))
480 }
481 _ => Err(Error::Unaddressable),
482 }
483 })?;
484
485 #[cfg(feature = "async")]
486 self.tx_waker.wake();
487
488 Ok(())
489 }
490
491 pub(crate) fn poll_at(&self, _cx: &mut Context) -> PollAt {
492 if self.tx_buffer.is_empty() {
493 PollAt::Ingress
494 } else {
495 PollAt::Now
496 }
497 }
498}
499
500#[cfg(test)]
501mod tests_common {
502 pub use super::*;
503 pub use crate::phy::DeviceCapabilities;
504 pub use crate::wire::IpAddress;
505
506 pub fn buffer(packets: usize) -> IcmpSocketBuffer<'static> {
507 IcmpSocketBuffer::new(
508 vec![IcmpPacketMetadata::EMPTY; packets],
509 vec![0; 66 * packets],
510 )
511 }
512
513 pub fn socket(
514 rx_buffer: IcmpSocketBuffer<'static>,
515 tx_buffer: IcmpSocketBuffer<'static>,
516 ) -> IcmpSocket<'static> {
517 IcmpSocket::new(rx_buffer, tx_buffer)
518 }
519
520 pub const LOCAL_PORT: u16 = 53;
521
522 pub static UDP_REPR: UdpRepr = UdpRepr {
523 src_port: 53,
524 dst_port: 9090,
525 };
526
527 pub static UDP_PAYLOAD: &[u8] = &[0xff; 10];
528}
529
530#[cfg(all(test, feature = "proto-ipv4"))]
531mod test_ipv4 {
532 use super::tests_common::*;
533
534 use crate::wire::Icmpv4DstUnreachable;
535
536 const REMOTE_IPV4: Ipv4Address = Ipv4Address([0x7f, 0x00, 0x00, 0x02]);
537 const LOCAL_IPV4: Ipv4Address = Ipv4Address([0x7f, 0x00, 0x00, 0x01]);
538 const LOCAL_END_V4: IpEndpoint = IpEndpoint {
539 addr: IpAddress::Ipv4(LOCAL_IPV4),
540 port: LOCAL_PORT,
541 };
542
543 static ECHOV4_REPR: Icmpv4Repr = Icmpv4Repr::EchoRequest {
544 ident: 0x1234,
545 seq_no: 0x5678,
546 data: &[0xff; 16],
547 };
548
549 static LOCAL_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr {
550 src_addr: Ipv4Address::UNSPECIFIED,
551 dst_addr: REMOTE_IPV4,
552 protocol: IpProtocol::Icmp,
553 payload_len: 24,
554 hop_limit: 0x40,
555 });
556
557 static REMOTE_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr {
558 src_addr: REMOTE_IPV4,
559 dst_addr: LOCAL_IPV4,
560 protocol: IpProtocol::Icmp,
561 payload_len: 24,
562 hop_limit: 0x40,
563 });
564
565 #[test]
566 fn test_send_unaddressable() {
567 let mut socket = socket(buffer(0), buffer(1));
568 assert_eq!(
569 socket.send_slice(b"abcdef", IpAddress::default()),
570 Err(Error::Unaddressable)
571 );
572 assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV4.into()), Ok(()));
573 }
574
575 #[test]
576 fn test_send_dispatch() {
577 let mut socket = socket(buffer(0), buffer(1));
578 let mut cx = Context::mock();
579 let checksum = ChecksumCapabilities::default();
580
581 assert_eq!(
582 socket.dispatch(&mut cx, |_, _| unreachable!()),
583 Err(Error::Exhausted)
584 );
585
586 assert_eq!(
588 socket.send_slice(&[0xff; 67], REMOTE_IPV4.into()),
589 Err(Error::Truncated)
590 );
591 assert!(socket.can_send());
592
593 let mut bytes = [0xff; 24];
594 let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
595 ECHOV4_REPR.emit(&mut packet, &checksum);
596
597 assert_eq!(
598 socket.send_slice(&packet.into_inner()[..], REMOTE_IPV4.into()),
599 Ok(())
600 );
601 assert_eq!(
602 socket.send_slice(b"123456", REMOTE_IPV4.into()),
603 Err(Error::Exhausted)
604 );
605 assert!(!socket.can_send());
606
607 assert_eq!(
608 socket.dispatch(&mut cx, |_, (ip_repr, icmp_repr)| {
609 assert_eq!(ip_repr, LOCAL_IPV4_REPR);
610 assert_eq!(icmp_repr, ECHOV4_REPR.into());
611 Err(Error::Unaddressable)
612 }),
613 Err(Error::Unaddressable)
614 );
615 assert!(!socket.can_send());
617
618 assert_eq!(
619 socket.dispatch(&mut cx, |_, (ip_repr, icmp_repr)| {
620 assert_eq!(ip_repr, LOCAL_IPV4_REPR);
621 assert_eq!(icmp_repr, ECHOV4_REPR.into());
622 Ok(())
623 }),
624 Ok(())
625 );
626 assert!(socket.can_send());
628 }
629
630 #[test]
631 fn test_set_hop_limit_v4() {
632 let mut s = socket(buffer(0), buffer(1));
633 let mut cx = Context::mock();
634 let checksum = ChecksumCapabilities::default();
635
636 let mut bytes = [0xff; 24];
637 let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
638 ECHOV4_REPR.emit(&mut packet, &checksum);
639
640 s.set_hop_limit(Some(0x2a));
641
642 assert_eq!(
643 s.send_slice(&packet.into_inner()[..], REMOTE_IPV4.into()),
644 Ok(())
645 );
646 assert_eq!(
647 s.dispatch(&mut cx, |_, (ip_repr, _)| {
648 assert_eq!(
649 ip_repr,
650 IpRepr::Ipv4(Ipv4Repr {
651 src_addr: Ipv4Address::UNSPECIFIED,
652 dst_addr: REMOTE_IPV4,
653 protocol: IpProtocol::Icmp,
654 payload_len: ECHOV4_REPR.buffer_len(),
655 hop_limit: 0x2a,
656 })
657 );
658 Ok(())
659 }),
660 Ok(())
661 );
662 }
663
664 #[test]
665 fn test_recv_process() {
666 let mut socket = socket(buffer(1), buffer(1));
667 let mut cx = Context::mock();
668 assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
669
670 assert!(!socket.can_recv());
671 assert_eq!(socket.recv(), Err(Error::Exhausted));
672
673 let checksum = ChecksumCapabilities::default();
674
675 let mut bytes = [0xff; 24];
676 let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
677 ECHOV4_REPR.emit(&mut packet, &checksum);
678 let data = &packet.into_inner()[..];
679
680 assert!(socket.accepts(&mut cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()));
681 assert_eq!(
682 socket.process(&mut cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()),
683 Ok(())
684 );
685 assert!(socket.can_recv());
686
687 assert!(socket.accepts(&mut cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()));
688 assert_eq!(
689 socket.process(&mut cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()),
690 Err(Error::Exhausted)
691 );
692
693 assert_eq!(socket.recv(), Ok((data, REMOTE_IPV4.into())));
694 assert!(!socket.can_recv());
695 }
696
697 #[test]
698 fn test_accept_bad_id() {
699 let mut socket = socket(buffer(1), buffer(1));
700 let mut cx = Context::mock();
701 assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
702
703 let checksum = ChecksumCapabilities::default();
704 let mut bytes = [0xff; 20];
705 let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
706 let icmp_repr = Icmpv4Repr::EchoRequest {
707 ident: 0x4321,
708 seq_no: 0x5678,
709 data: &[0xff; 16],
710 };
711 icmp_repr.emit(&mut packet, &checksum);
712
713 assert!(!socket.accepts(&mut cx, &REMOTE_IPV4_REPR, &icmp_repr.into()));
716 }
717
718 #[test]
719 fn test_accepts_udp() {
720 let mut socket = socket(buffer(1), buffer(1));
721 let mut cx = Context::mock();
722 assert_eq!(socket.bind(Endpoint::Udp(LOCAL_END_V4)), Ok(()));
723
724 let checksum = ChecksumCapabilities::default();
725
726 let mut bytes = [0xff; 18];
727 let mut packet = UdpPacket::new_unchecked(&mut bytes);
728 UDP_REPR.emit(
729 &mut packet,
730 &REMOTE_IPV4.into(),
731 &LOCAL_IPV4.into(),
732 UDP_PAYLOAD.len(),
733 |buf| buf.copy_from_slice(UDP_PAYLOAD),
734 &checksum,
735 );
736
737 let data = &packet.into_inner()[..];
738
739 let icmp_repr = Icmpv4Repr::DstUnreachable {
740 reason: Icmpv4DstUnreachable::PortUnreachable,
741 header: Ipv4Repr {
742 src_addr: LOCAL_IPV4,
743 dst_addr: REMOTE_IPV4,
744 protocol: IpProtocol::Icmp,
745 payload_len: 12,
746 hop_limit: 0x40,
747 },
748 data: data,
749 };
750 let ip_repr = IpRepr::Unspecified {
751 src_addr: REMOTE_IPV4.into(),
752 dst_addr: LOCAL_IPV4.into(),
753 protocol: IpProtocol::Icmp,
754 payload_len: icmp_repr.buffer_len(),
755 hop_limit: 0x40,
756 };
757
758 assert!(!socket.can_recv());
759
760 assert!(socket.accepts(&mut cx, &ip_repr, &icmp_repr.into()));
763 assert_eq!(socket.process(&mut cx, &ip_repr, &icmp_repr.into()), Ok(()));
764 assert!(socket.can_recv());
765
766 let mut bytes = [0x00; 46];
767 let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]);
768 icmp_repr.emit(&mut packet, &checksum);
769 assert_eq!(
770 socket.recv(),
771 Ok((&packet.into_inner()[..], REMOTE_IPV4.into()))
772 );
773 assert!(!socket.can_recv());
774 }
775}
776
777#[cfg(all(test, feature = "proto-ipv6"))]
778mod test_ipv6 {
779 use super::tests_common::*;
780
781 use crate::wire::Icmpv6DstUnreachable;
782
783 const REMOTE_IPV6: Ipv6Address =
784 Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
785 const LOCAL_IPV6: Ipv6Address =
786 Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
787 const LOCAL_END_V6: IpEndpoint = IpEndpoint {
788 addr: IpAddress::Ipv6(LOCAL_IPV6),
789 port: LOCAL_PORT,
790 };
791 static ECHOV6_REPR: Icmpv6Repr = Icmpv6Repr::EchoRequest {
792 ident: 0x1234,
793 seq_no: 0x5678,
794 data: &[0xff; 16],
795 };
796
797 static LOCAL_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
798 src_addr: Ipv6Address::UNSPECIFIED,
799 dst_addr: REMOTE_IPV6,
800 next_header: IpProtocol::Icmpv6,
801 payload_len: 24,
802 hop_limit: 0x40,
803 });
804
805 static REMOTE_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
806 src_addr: REMOTE_IPV6,
807 dst_addr: LOCAL_IPV6,
808 next_header: IpProtocol::Icmpv6,
809 payload_len: 24,
810 hop_limit: 0x40,
811 });
812
813 #[test]
814 fn test_send_unaddressable() {
815 let mut socket = socket(buffer(0), buffer(1));
816 assert_eq!(
817 socket.send_slice(b"abcdef", IpAddress::default()),
818 Err(Error::Unaddressable)
819 );
820 assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV6.into()), Ok(()));
821 }
822
823 #[test]
824 fn test_send_dispatch() {
825 let mut socket = socket(buffer(0), buffer(1));
826 let mut cx = Context::mock();
827 let checksum = ChecksumCapabilities::default();
828
829 assert_eq!(
830 socket.dispatch(&mut cx, |_, _| unreachable!()),
831 Err(Error::Exhausted)
832 );
833
834 assert_eq!(
836 socket.send_slice(&[0xff; 67], REMOTE_IPV6.into()),
837 Err(Error::Truncated)
838 );
839 assert!(socket.can_send());
840
841 let mut bytes = vec![0xff; 24];
842 let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
843 ECHOV6_REPR.emit(
844 &LOCAL_IPV6.into(),
845 &REMOTE_IPV6.into(),
846 &mut packet,
847 &checksum,
848 );
849
850 assert_eq!(
851 socket.send_slice(&packet.into_inner()[..], REMOTE_IPV6.into()),
852 Ok(())
853 );
854 assert_eq!(
855 socket.send_slice(b"123456", REMOTE_IPV6.into()),
856 Err(Error::Exhausted)
857 );
858 assert!(!socket.can_send());
859
860 assert_eq!(
861 socket.dispatch(&mut cx, |_, (ip_repr, icmp_repr)| {
862 assert_eq!(ip_repr, LOCAL_IPV6_REPR);
863 assert_eq!(icmp_repr, ECHOV6_REPR.into());
864 Err(Error::Unaddressable)
865 }),
866 Err(Error::Unaddressable)
867 );
868 assert!(!socket.can_send());
870
871 assert_eq!(
872 socket.dispatch(&mut cx, |_, (ip_repr, icmp_repr)| {
873 assert_eq!(ip_repr, LOCAL_IPV6_REPR);
874 assert_eq!(icmp_repr, ECHOV6_REPR.into());
875 Ok(())
876 }),
877 Ok(())
878 );
879 assert!(socket.can_send());
881 }
882
883 #[test]
884 fn test_set_hop_limit() {
885 let mut s = socket(buffer(0), buffer(1));
886 let mut cx = Context::mock();
887 let checksum = ChecksumCapabilities::default();
888
889 let mut bytes = vec![0xff; 24];
890 let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
891 ECHOV6_REPR.emit(
892 &LOCAL_IPV6.into(),
893 &REMOTE_IPV6.into(),
894 &mut packet,
895 &checksum,
896 );
897
898 s.set_hop_limit(Some(0x2a));
899
900 assert_eq!(
901 s.send_slice(&packet.into_inner()[..], REMOTE_IPV6.into()),
902 Ok(())
903 );
904 assert_eq!(
905 s.dispatch(&mut cx, |_, (ip_repr, _)| {
906 assert_eq!(
907 ip_repr,
908 IpRepr::Ipv6(Ipv6Repr {
909 src_addr: Ipv6Address::UNSPECIFIED,
910 dst_addr: REMOTE_IPV6,
911 next_header: IpProtocol::Icmpv6,
912 payload_len: ECHOV6_REPR.buffer_len(),
913 hop_limit: 0x2a,
914 })
915 );
916 Ok(())
917 }),
918 Ok(())
919 );
920 }
921
922 #[test]
923 fn test_recv_process() {
924 let mut socket = socket(buffer(1), buffer(1));
925 let mut cx = Context::mock();
926 assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
927
928 assert!(!socket.can_recv());
929 assert_eq!(socket.recv(), Err(Error::Exhausted));
930
931 let checksum = ChecksumCapabilities::default();
932
933 let mut bytes = [0xff; 24];
934 let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
935 ECHOV6_REPR.emit(
936 &LOCAL_IPV6.into(),
937 &REMOTE_IPV6.into(),
938 &mut packet,
939 &checksum,
940 );
941 let data = &packet.into_inner()[..];
942
943 assert!(socket.accepts(&mut cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
944 assert_eq!(
945 socket.process(&mut cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()),
946 Ok(())
947 );
948 assert!(socket.can_recv());
949
950 assert!(socket.accepts(&mut cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
951 assert_eq!(
952 socket.process(&mut cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()),
953 Err(Error::Exhausted)
954 );
955
956 assert_eq!(socket.recv(), Ok((data, REMOTE_IPV6.into())));
957 assert!(!socket.can_recv());
958 }
959
960 #[test]
961 fn test_accept_bad_id() {
962 let mut socket = socket(buffer(1), buffer(1));
963 let mut cx = Context::mock();
964 assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
965
966 let checksum = ChecksumCapabilities::default();
967 let mut bytes = [0xff; 20];
968 let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
969 let icmp_repr = Icmpv6Repr::EchoRequest {
970 ident: 0x4321,
971 seq_no: 0x5678,
972 data: &[0xff; 16],
973 };
974 icmp_repr.emit(
975 &LOCAL_IPV6.into(),
976 &REMOTE_IPV6.into(),
977 &mut packet,
978 &checksum,
979 );
980
981 assert!(!socket.accepts(&mut cx, &REMOTE_IPV6_REPR, &icmp_repr.into()));
984 }
985
986 #[test]
987 fn test_accepts_udp() {
988 let mut socket = socket(buffer(1), buffer(1));
989 let mut cx = Context::mock();
990 assert_eq!(socket.bind(Endpoint::Udp(LOCAL_END_V6)), Ok(()));
991
992 let checksum = ChecksumCapabilities::default();
993
994 let mut bytes = [0xff; 18];
995 let mut packet = UdpPacket::new_unchecked(&mut bytes);
996 UDP_REPR.emit(
997 &mut packet,
998 &REMOTE_IPV6.into(),
999 &LOCAL_IPV6.into(),
1000 UDP_PAYLOAD.len(),
1001 |buf| buf.copy_from_slice(UDP_PAYLOAD),
1002 &checksum,
1003 );
1004
1005 let data = &packet.into_inner()[..];
1006
1007 let icmp_repr = Icmpv6Repr::DstUnreachable {
1008 reason: Icmpv6DstUnreachable::PortUnreachable,
1009 header: Ipv6Repr {
1010 src_addr: LOCAL_IPV6,
1011 dst_addr: REMOTE_IPV6,
1012 next_header: IpProtocol::Icmpv6,
1013 payload_len: 12,
1014 hop_limit: 0x40,
1015 },
1016 data: data,
1017 };
1018 let ip_repr = IpRepr::Unspecified {
1019 src_addr: REMOTE_IPV6.into(),
1020 dst_addr: LOCAL_IPV6.into(),
1021 protocol: IpProtocol::Icmpv6,
1022 payload_len: icmp_repr.buffer_len(),
1023 hop_limit: 0x40,
1024 };
1025
1026 assert!(!socket.can_recv());
1027
1028 assert!(socket.accepts(&mut cx, &ip_repr, &icmp_repr.into()));
1031 assert_eq!(socket.process(&mut cx, &ip_repr, &icmp_repr.into()), Ok(()));
1032 assert!(socket.can_recv());
1033
1034 let mut bytes = [0x00; 66];
1035 let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]);
1036 icmp_repr.emit(
1037 &LOCAL_IPV6.into(),
1038 &REMOTE_IPV6.into(),
1039 &mut packet,
1040 &checksum,
1041 );
1042 assert_eq!(
1043 socket.recv(),
1044 Ok((&packet.into_inner()[..], REMOTE_IPV6.into()))
1045 );
1046 assert!(!socket.can_recv());
1047 }
1048}