icmp.rs 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195
  1. use core::cmp;
  2. #[cfg(feature = "async")]
  3. use core::task::Waker;
  4. use crate::phy::ChecksumCapabilities;
  5. #[cfg(feature = "async")]
  6. use crate::socket::WakerRegistration;
  7. use crate::socket::{Context, PollAt};
  8. use crate::storage::Empty;
  9. use crate::wire::IcmpRepr;
  10. #[cfg(feature = "proto-ipv4")]
  11. use crate::wire::{Icmpv4Packet, Icmpv4Repr, Ipv4Repr};
  12. #[cfg(feature = "proto-ipv6")]
  13. use crate::wire::{Icmpv6Packet, Icmpv6Repr, Ipv6Repr};
  14. use crate::wire::{IpAddress, IpListenEndpoint, IpProtocol, IpRepr};
  15. use crate::wire::{UdpPacket, UdpRepr};
  16. /// Error returned by [`Socket::bind`]
  17. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  18. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  19. pub enum BindError {
  20. InvalidState,
  21. Unaddressable,
  22. }
  23. impl core::fmt::Display for BindError {
  24. fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
  25. match self {
  26. BindError::InvalidState => write!(f, "invalid state"),
  27. BindError::Unaddressable => write!(f, "unaddressable"),
  28. }
  29. }
  30. }
  31. #[cfg(feature = "std")]
  32. impl std::error::Error for BindError {}
  33. /// Error returned by [`Socket::send`]
  34. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  35. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  36. pub enum SendError {
  37. Unaddressable,
  38. BufferFull,
  39. }
  40. impl core::fmt::Display for SendError {
  41. fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
  42. match self {
  43. SendError::Unaddressable => write!(f, "unaddressable"),
  44. SendError::BufferFull => write!(f, "buffer full"),
  45. }
  46. }
  47. }
  48. #[cfg(feature = "std")]
  49. impl std::error::Error for SendError {}
  50. /// Error returned by [`Socket::recv`]
  51. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  52. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  53. pub enum RecvError {
  54. Exhausted,
  55. }
  56. impl core::fmt::Display for RecvError {
  57. fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
  58. match self {
  59. RecvError::Exhausted => write!(f, "exhausted"),
  60. }
  61. }
  62. }
  63. #[cfg(feature = "std")]
  64. impl std::error::Error for RecvError {}
  65. /// Type of endpoint to bind the ICMP socket to. See [IcmpSocket::bind] for
  66. /// more details.
  67. ///
  68. /// [IcmpSocket::bind]: struct.IcmpSocket.html#method.bind
  69. #[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
  70. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  71. pub enum Endpoint {
  72. #[default]
  73. Unspecified,
  74. Ident(u16),
  75. Udp(IpListenEndpoint),
  76. }
  77. impl Endpoint {
  78. pub fn is_specified(&self) -> bool {
  79. match *self {
  80. Endpoint::Ident(_) => true,
  81. Endpoint::Udp(endpoint) => endpoint.port != 0,
  82. Endpoint::Unspecified => false,
  83. }
  84. }
  85. }
  86. /// An ICMP packet metadata.
  87. pub type PacketMetadata = crate::storage::PacketMetadata<IpAddress>;
  88. /// An ICMP packet ring buffer.
  89. pub type PacketBuffer<'a> = crate::storage::PacketBuffer<'a, IpAddress>;
  90. /// A ICMP socket
  91. ///
  92. /// An ICMP socket is bound to a specific [IcmpEndpoint] which may
  93. /// be a specific UDP port to listen for ICMP error messages related
  94. /// to the port or a specific ICMP identifier value. See [bind] for
  95. /// more details.
  96. ///
  97. /// [IcmpEndpoint]: enum.IcmpEndpoint.html
  98. /// [bind]: #method.bind
  99. #[derive(Debug)]
  100. pub struct Socket<'a> {
  101. rx_buffer: PacketBuffer<'a>,
  102. tx_buffer: PacketBuffer<'a>,
  103. /// The endpoint this socket is communicating with
  104. endpoint: Endpoint,
  105. /// The time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
  106. hop_limit: Option<u8>,
  107. #[cfg(feature = "async")]
  108. rx_waker: WakerRegistration,
  109. #[cfg(feature = "async")]
  110. tx_waker: WakerRegistration,
  111. }
  112. impl<'a> Socket<'a> {
  113. /// Create an ICMP socket with the given buffers.
  114. pub fn new(rx_buffer: PacketBuffer<'a>, tx_buffer: PacketBuffer<'a>) -> Socket<'a> {
  115. Socket {
  116. rx_buffer: rx_buffer,
  117. tx_buffer: tx_buffer,
  118. endpoint: Default::default(),
  119. hop_limit: None,
  120. #[cfg(feature = "async")]
  121. rx_waker: WakerRegistration::new(),
  122. #[cfg(feature = "async")]
  123. tx_waker: WakerRegistration::new(),
  124. }
  125. }
  126. /// Register a waker for receive operations.
  127. ///
  128. /// The waker is woken on state changes that might affect the return value
  129. /// of `recv` method calls, such as receiving data, or the socket closing.
  130. ///
  131. /// Notes:
  132. ///
  133. /// - Only one waker can be registered at a time. If another waker was previously registered,
  134. /// it is overwritten and will no longer be woken.
  135. /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes.
  136. /// - "Spurious wakes" are allowed: a wake doesn't guarantee the result of `recv` has
  137. /// necessarily changed.
  138. #[cfg(feature = "async")]
  139. pub fn register_recv_waker(&mut self, waker: &Waker) {
  140. self.rx_waker.register(waker)
  141. }
  142. /// Register a waker for send operations.
  143. ///
  144. /// The waker is woken on state changes that might affect the return value
  145. /// of `send` method calls, such as space becoming available in the transmit
  146. /// buffer, or the socket closing.
  147. ///
  148. /// Notes:
  149. ///
  150. /// - Only one waker can be registered at a time. If another waker was previously registered,
  151. /// it is overwritten and will no longer be woken.
  152. /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes.
  153. /// - "Spurious wakes" are allowed: a wake doesn't guarantee the result of `send` has
  154. /// necessarily changed.
  155. #[cfg(feature = "async")]
  156. pub fn register_send_waker(&mut self, waker: &Waker) {
  157. self.tx_waker.register(waker)
  158. }
  159. /// Return the time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
  160. ///
  161. /// See also the [set_hop_limit](#method.set_hop_limit) method
  162. pub fn hop_limit(&self) -> Option<u8> {
  163. self.hop_limit
  164. }
  165. /// Set the time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
  166. ///
  167. /// A socket without an explicitly set hop limit value uses the default [IANA recommended]
  168. /// value (64).
  169. ///
  170. /// # Panics
  171. ///
  172. /// This function panics if a hop limit value of 0 is given. See [RFC 1122 § 3.2.1.7].
  173. ///
  174. /// [IANA recommended]: https://www.iana.org/assignments/ip-parameters/ip-parameters.xhtml
  175. /// [RFC 1122 § 3.2.1.7]: https://tools.ietf.org/html/rfc1122#section-3.2.1.7
  176. pub fn set_hop_limit(&mut self, hop_limit: Option<u8>) {
  177. // A host MUST NOT send a datagram with a hop limit value of 0
  178. if let Some(0) = hop_limit {
  179. panic!("the time-to-live value of a packet must not be zero")
  180. }
  181. self.hop_limit = hop_limit
  182. }
  183. /// Bind the socket to the given endpoint.
  184. ///
  185. /// This function returns `Err(Error::Illegal)` if the socket was open
  186. /// (see [is_open](#method.is_open)), and `Err(Error::Unaddressable)`
  187. /// if `endpoint` is unspecified (see [is_specified]).
  188. ///
  189. /// # Examples
  190. ///
  191. /// ## Bind to ICMP Error messages associated with a specific UDP port:
  192. ///
  193. /// To [recv] ICMP error messages that are associated with a specific local
  194. /// UDP port, the socket may be bound to a given port using [IcmpEndpoint::Udp].
  195. /// This may be useful for applications using UDP attempting to detect and/or
  196. /// diagnose connection problems.
  197. ///
  198. /// ```
  199. /// use smoltcp::wire::IpListenEndpoint;
  200. /// use smoltcp::socket::icmp;
  201. /// # let rx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 20]);
  202. /// # let tx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 20]);
  203. ///
  204. /// let mut icmp_socket = // ...
  205. /// # icmp::Socket::new(rx_buffer, tx_buffer);
  206. ///
  207. /// // Bind to ICMP error responses for UDP packets sent from port 53.
  208. /// let endpoint = IpListenEndpoint::from(53);
  209. /// icmp_socket.bind(icmp::Endpoint::Udp(endpoint)).unwrap();
  210. /// ```
  211. ///
  212. /// ## Bind to a specific ICMP identifier:
  213. ///
  214. /// To [send] and [recv] ICMP packets that are not associated with a specific UDP
  215. /// port, the socket may be bound to a specific ICMP identifier using
  216. /// [IcmpEndpoint::Ident]. This is useful for sending and receiving Echo Request/Reply
  217. /// messages.
  218. ///
  219. /// ```
  220. /// use smoltcp::wire::IpListenEndpoint;
  221. /// use smoltcp::socket::icmp;
  222. /// # let rx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 20]);
  223. /// # let tx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 20]);
  224. ///
  225. /// let mut icmp_socket = // ...
  226. /// # icmp::Socket::new(rx_buffer, tx_buffer);
  227. ///
  228. /// // Bind to ICMP messages with the ICMP identifier 0x1234
  229. /// icmp_socket.bind(icmp::Endpoint::Ident(0x1234)).unwrap();
  230. /// ```
  231. ///
  232. /// [is_specified]: enum.IcmpEndpoint.html#method.is_specified
  233. /// [IcmpEndpoint::Ident]: enum.IcmpEndpoint.html#variant.Ident
  234. /// [IcmpEndpoint::Udp]: enum.IcmpEndpoint.html#variant.Udp
  235. /// [send]: #method.send
  236. /// [recv]: #method.recv
  237. pub fn bind<T: Into<Endpoint>>(&mut self, endpoint: T) -> Result<(), BindError> {
  238. let endpoint = endpoint.into();
  239. if !endpoint.is_specified() {
  240. return Err(BindError::Unaddressable);
  241. }
  242. if self.is_open() {
  243. return Err(BindError::InvalidState);
  244. }
  245. self.endpoint = endpoint;
  246. #[cfg(feature = "async")]
  247. {
  248. self.rx_waker.wake();
  249. self.tx_waker.wake();
  250. }
  251. Ok(())
  252. }
  253. /// Check whether the transmit buffer is full.
  254. #[inline]
  255. pub fn can_send(&self) -> bool {
  256. !self.tx_buffer.is_full()
  257. }
  258. /// Check whether the receive buffer is not empty.
  259. #[inline]
  260. pub fn can_recv(&self) -> bool {
  261. !self.rx_buffer.is_empty()
  262. }
  263. /// Return the maximum number packets the socket can receive.
  264. #[inline]
  265. pub fn packet_recv_capacity(&self) -> usize {
  266. self.rx_buffer.packet_capacity()
  267. }
  268. /// Return the maximum number packets the socket can transmit.
  269. #[inline]
  270. pub fn packet_send_capacity(&self) -> usize {
  271. self.tx_buffer.packet_capacity()
  272. }
  273. /// Return the maximum number of bytes inside the recv buffer.
  274. #[inline]
  275. pub fn payload_recv_capacity(&self) -> usize {
  276. self.rx_buffer.payload_capacity()
  277. }
  278. /// Return the maximum number of bytes inside the transmit buffer.
  279. #[inline]
  280. pub fn payload_send_capacity(&self) -> usize {
  281. self.tx_buffer.payload_capacity()
  282. }
  283. /// Check whether the socket is open.
  284. #[inline]
  285. pub fn is_open(&self) -> bool {
  286. self.endpoint != Endpoint::Unspecified
  287. }
  288. /// Enqueue a packet to be sent to a given remote address, and return a pointer
  289. /// to its payload.
  290. ///
  291. /// This function returns `Err(Error::Exhausted)` if the transmit buffer is full,
  292. /// `Err(Error::Truncated)` if the requested size is larger than the packet buffer
  293. /// size, and `Err(Error::Unaddressable)` if the remote address is unspecified.
  294. pub fn send(&mut self, size: usize, endpoint: IpAddress) -> Result<&mut [u8], SendError> {
  295. if endpoint.is_unspecified() {
  296. return Err(SendError::Unaddressable);
  297. }
  298. let packet_buf = self
  299. .tx_buffer
  300. .enqueue(size, endpoint)
  301. .map_err(|_| SendError::BufferFull)?;
  302. net_trace!("icmp:{}: buffer to send {} octets", endpoint, size);
  303. Ok(packet_buf)
  304. }
  305. /// Enqueue a packet to be send to a given remote address and pass the buffer
  306. /// to the provided closure. The closure then returns the size of the data written
  307. /// into the buffer.
  308. ///
  309. /// Also see [send](#method.send).
  310. pub fn send_with<F>(
  311. &mut self,
  312. max_size: usize,
  313. endpoint: IpAddress,
  314. f: F,
  315. ) -> Result<usize, SendError>
  316. where
  317. F: FnOnce(&mut [u8]) -> usize,
  318. {
  319. if endpoint.is_unspecified() {
  320. return Err(SendError::Unaddressable);
  321. }
  322. let size = self
  323. .tx_buffer
  324. .enqueue_with_infallible(max_size, endpoint, f)
  325. .map_err(|_| SendError::BufferFull)?;
  326. net_trace!("icmp:{}: buffer to send {} octets", endpoint, size);
  327. Ok(size)
  328. }
  329. /// Enqueue a packet to be sent to a given remote address, and fill it from a slice.
  330. ///
  331. /// See also [send](#method.send).
  332. pub fn send_slice(&mut self, data: &[u8], endpoint: IpAddress) -> Result<(), SendError> {
  333. let packet_buf = self.send(data.len(), endpoint)?;
  334. packet_buf.copy_from_slice(data);
  335. Ok(())
  336. }
  337. /// Dequeue a packet received from a remote endpoint, and return the `IpAddress` as well
  338. /// as a pointer to the payload.
  339. ///
  340. /// This function returns `Err(Error::Exhausted)` if the receive buffer is empty.
  341. pub fn recv(&mut self) -> Result<(&[u8], IpAddress), RecvError> {
  342. let (endpoint, packet_buf) = self.rx_buffer.dequeue().map_err(|_| RecvError::Exhausted)?;
  343. net_trace!(
  344. "icmp:{}: receive {} buffered octets",
  345. endpoint,
  346. packet_buf.len()
  347. );
  348. Ok((packet_buf, endpoint))
  349. }
  350. /// Dequeue a packet received from a remote endpoint, copy the payload into the given slice,
  351. /// and return the amount of octets copied as well as the `IpAddress`
  352. ///
  353. /// See also [recv](#method.recv).
  354. pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<(usize, IpAddress), RecvError> {
  355. let (buffer, endpoint) = self.recv()?;
  356. let length = cmp::min(data.len(), buffer.len());
  357. data[..length].copy_from_slice(&buffer[..length]);
  358. Ok((length, endpoint))
  359. }
  360. /// Filter determining which packets received by the interface are appended to
  361. /// the given sockets received buffer.
  362. pub(crate) fn accepts(&self, cx: &mut Context, ip_repr: &IpRepr, icmp_repr: &IcmpRepr) -> bool {
  363. match (&self.endpoint, icmp_repr) {
  364. // If we are bound to ICMP errors associated to a UDP port, only
  365. // accept Destination Unreachable or Time Exceeded messages with
  366. // the data containing a UDP packet send from the local port we
  367. // are bound to.
  368. #[cfg(feature = "proto-ipv4")]
  369. (
  370. &Endpoint::Udp(endpoint),
  371. &IcmpRepr::Ipv4(
  372. Icmpv4Repr::DstUnreachable { data, header, .. }
  373. | Icmpv4Repr::TimeExceeded { data, header, .. },
  374. ),
  375. ) if endpoint.addr.is_none() || endpoint.addr == Some(ip_repr.dst_addr()) => {
  376. let packet = UdpPacket::new_unchecked(data);
  377. match UdpRepr::parse(
  378. &packet,
  379. &header.src_addr.into(),
  380. &header.dst_addr.into(),
  381. &cx.checksum_caps(),
  382. ) {
  383. Ok(repr) => endpoint.port == repr.src_port,
  384. Err(_) => false,
  385. }
  386. }
  387. #[cfg(feature = "proto-ipv6")]
  388. (
  389. &Endpoint::Udp(endpoint),
  390. &IcmpRepr::Ipv6(
  391. Icmpv6Repr::DstUnreachable { data, header, .. }
  392. | Icmpv6Repr::TimeExceeded { data, header, .. },
  393. ),
  394. ) if endpoint.addr.is_none() || endpoint.addr == Some(ip_repr.dst_addr()) => {
  395. let packet = UdpPacket::new_unchecked(data);
  396. match UdpRepr::parse(
  397. &packet,
  398. &header.src_addr.into(),
  399. &header.dst_addr.into(),
  400. &cx.checksum_caps(),
  401. ) {
  402. Ok(repr) => endpoint.port == repr.src_port,
  403. Err(_) => false,
  404. }
  405. }
  406. // If we are bound to a specific ICMP identifier value, only accept an
  407. // Echo Request/Reply with the identifier field matching the endpoint
  408. // port.
  409. #[cfg(feature = "proto-ipv4")]
  410. (
  411. &Endpoint::Ident(bound_ident),
  412. &IcmpRepr::Ipv4(Icmpv4Repr::EchoRequest { ident, .. }),
  413. )
  414. | (
  415. &Endpoint::Ident(bound_ident),
  416. &IcmpRepr::Ipv4(Icmpv4Repr::EchoReply { ident, .. }),
  417. ) => ident == bound_ident,
  418. #[cfg(feature = "proto-ipv6")]
  419. (
  420. &Endpoint::Ident(bound_ident),
  421. &IcmpRepr::Ipv6(Icmpv6Repr::EchoRequest { ident, .. }),
  422. )
  423. | (
  424. &Endpoint::Ident(bound_ident),
  425. &IcmpRepr::Ipv6(Icmpv6Repr::EchoReply { ident, .. }),
  426. ) => ident == bound_ident,
  427. _ => false,
  428. }
  429. }
  430. pub(crate) fn process(&mut self, _cx: &mut Context, ip_repr: &IpRepr, icmp_repr: &IcmpRepr) {
  431. match icmp_repr {
  432. #[cfg(feature = "proto-ipv4")]
  433. IcmpRepr::Ipv4(icmp_repr) => {
  434. net_trace!("icmp: receiving {} octets", icmp_repr.buffer_len());
  435. match self
  436. .rx_buffer
  437. .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())
  438. {
  439. Ok(packet_buf) => {
  440. icmp_repr.emit(
  441. &mut Icmpv4Packet::new_unchecked(packet_buf),
  442. &ChecksumCapabilities::default(),
  443. );
  444. }
  445. Err(_) => net_trace!("icmp: buffer full, dropped incoming packet"),
  446. }
  447. }
  448. #[cfg(feature = "proto-ipv6")]
  449. IcmpRepr::Ipv6(icmp_repr) => {
  450. net_trace!("icmp: receiving {} octets", icmp_repr.buffer_len());
  451. match self
  452. .rx_buffer
  453. .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())
  454. {
  455. Ok(packet_buf) => icmp_repr.emit(
  456. &ip_repr.src_addr(),
  457. &ip_repr.dst_addr(),
  458. &mut Icmpv6Packet::new_unchecked(packet_buf),
  459. &ChecksumCapabilities::default(),
  460. ),
  461. Err(_) => net_trace!("icmp: buffer full, dropped incoming packet"),
  462. }
  463. }
  464. }
  465. #[cfg(feature = "async")]
  466. self.rx_waker.wake();
  467. }
  468. pub(crate) fn dispatch<F, E>(&mut self, cx: &mut Context, emit: F) -> Result<(), E>
  469. where
  470. F: FnOnce(&mut Context, (IpRepr, IcmpRepr)) -> Result<(), E>,
  471. {
  472. let hop_limit = self.hop_limit.unwrap_or(64);
  473. let res = self.tx_buffer.dequeue_with(|remote_endpoint, packet_buf| {
  474. net_trace!(
  475. "icmp:{}: sending {} octets",
  476. remote_endpoint,
  477. packet_buf.len()
  478. );
  479. match *remote_endpoint {
  480. #[cfg(feature = "proto-ipv4")]
  481. IpAddress::Ipv4(dst_addr) => {
  482. let src_addr = match cx.get_source_address_ipv4(dst_addr) {
  483. Some(addr) => addr,
  484. None => {
  485. net_trace!(
  486. "icmp:{}: not find suitable source address, dropping",
  487. remote_endpoint
  488. );
  489. return Ok(());
  490. }
  491. };
  492. let packet = Icmpv4Packet::new_unchecked(&*packet_buf);
  493. let repr = match Icmpv4Repr::parse(&packet, &ChecksumCapabilities::ignored()) {
  494. Ok(x) => x,
  495. Err(_) => {
  496. net_trace!(
  497. "icmp:{}: malformed packet in queue, dropping",
  498. remote_endpoint
  499. );
  500. return Ok(());
  501. }
  502. };
  503. let ip_repr = IpRepr::Ipv4(Ipv4Repr {
  504. src_addr,
  505. dst_addr,
  506. next_header: IpProtocol::Icmp,
  507. payload_len: repr.buffer_len(),
  508. hop_limit: hop_limit,
  509. });
  510. emit(cx, (ip_repr, IcmpRepr::Ipv4(repr)))
  511. }
  512. #[cfg(feature = "proto-ipv6")]
  513. IpAddress::Ipv6(dst_addr) => {
  514. let src_addr = match cx.get_source_address_ipv6(dst_addr) {
  515. Some(addr) => addr,
  516. None => {
  517. net_trace!(
  518. "icmp:{}: not find suitable source address, dropping",
  519. remote_endpoint
  520. );
  521. return Ok(());
  522. }
  523. };
  524. let packet = Icmpv6Packet::new_unchecked(&*packet_buf);
  525. let repr = match Icmpv6Repr::parse(
  526. &src_addr.into(),
  527. &dst_addr.into(),
  528. &packet,
  529. &ChecksumCapabilities::ignored(),
  530. ) {
  531. Ok(x) => x,
  532. Err(_) => {
  533. net_trace!(
  534. "icmp:{}: malformed packet in queue, dropping",
  535. remote_endpoint
  536. );
  537. return Ok(());
  538. }
  539. };
  540. let ip_repr = IpRepr::Ipv6(Ipv6Repr {
  541. src_addr,
  542. dst_addr,
  543. next_header: IpProtocol::Icmpv6,
  544. payload_len: repr.buffer_len(),
  545. hop_limit: hop_limit,
  546. });
  547. emit(cx, (ip_repr, IcmpRepr::Ipv6(repr)))
  548. }
  549. }
  550. });
  551. match res {
  552. Err(Empty) => Ok(()),
  553. Ok(Err(e)) => Err(e),
  554. Ok(Ok(())) => {
  555. #[cfg(feature = "async")]
  556. self.tx_waker.wake();
  557. Ok(())
  558. }
  559. }
  560. }
  561. pub(crate) fn poll_at(&self, _cx: &mut Context) -> PollAt {
  562. if self.tx_buffer.is_empty() {
  563. PollAt::Ingress
  564. } else {
  565. PollAt::Now
  566. }
  567. }
  568. }
  569. #[cfg(test)]
  570. mod tests_common {
  571. pub use super::*;
  572. pub use crate::phy::DeviceCapabilities;
  573. pub use crate::wire::IpAddress;
  574. pub fn buffer(packets: usize) -> PacketBuffer<'static> {
  575. PacketBuffer::new(vec![PacketMetadata::EMPTY; packets], vec![0; 66 * packets])
  576. }
  577. pub fn socket(
  578. rx_buffer: PacketBuffer<'static>,
  579. tx_buffer: PacketBuffer<'static>,
  580. ) -> Socket<'static> {
  581. Socket::new(rx_buffer, tx_buffer)
  582. }
  583. pub const LOCAL_PORT: u16 = 53;
  584. pub static UDP_REPR: UdpRepr = UdpRepr {
  585. src_port: 53,
  586. dst_port: 9090,
  587. };
  588. pub static UDP_PAYLOAD: &[u8] = &[0xff; 10];
  589. }
  590. #[cfg(all(test, feature = "proto-ipv4"))]
  591. mod test_ipv4 {
  592. use crate::phy::Medium;
  593. use crate::tests::setup;
  594. use rstest::*;
  595. use super::tests_common::*;
  596. use crate::wire::{Icmpv4DstUnreachable, IpEndpoint, Ipv4Address};
  597. const REMOTE_IPV4: Ipv4Address = Ipv4Address([192, 168, 1, 2]);
  598. const LOCAL_IPV4: Ipv4Address = Ipv4Address([192, 168, 1, 1]);
  599. const LOCAL_END_V4: IpEndpoint = IpEndpoint {
  600. addr: IpAddress::Ipv4(LOCAL_IPV4),
  601. port: LOCAL_PORT,
  602. };
  603. static ECHOV4_REPR: Icmpv4Repr = Icmpv4Repr::EchoRequest {
  604. ident: 0x1234,
  605. seq_no: 0x5678,
  606. data: &[0xff; 16],
  607. };
  608. static LOCAL_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr {
  609. src_addr: LOCAL_IPV4,
  610. dst_addr: REMOTE_IPV4,
  611. next_header: IpProtocol::Icmp,
  612. payload_len: 24,
  613. hop_limit: 0x40,
  614. });
  615. static REMOTE_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr {
  616. src_addr: REMOTE_IPV4,
  617. dst_addr: LOCAL_IPV4,
  618. next_header: IpProtocol::Icmp,
  619. payload_len: 24,
  620. hop_limit: 0x40,
  621. });
  622. #[test]
  623. fn test_send_unaddressable() {
  624. let mut socket = socket(buffer(0), buffer(1));
  625. assert_eq!(
  626. socket.send_slice(b"abcdef", IpAddress::Ipv4(Ipv4Address::default())),
  627. Err(SendError::Unaddressable)
  628. );
  629. assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV4.into()), Ok(()));
  630. }
  631. #[rstest]
  632. #[case::ethernet(Medium::Ethernet)]
  633. #[cfg(feature = "medium-ethernet")]
  634. fn test_send_dispatch(#[case] medium: Medium) {
  635. let (mut iface, _, _) = setup(medium);
  636. let cx = iface.context();
  637. let mut socket = socket(buffer(0), buffer(1));
  638. let checksum = ChecksumCapabilities::default();
  639. assert_eq!(socket.dispatch(cx, |_, _| unreachable!()), Ok::<_, ()>(()));
  640. // This buffer is too long
  641. assert_eq!(
  642. socket.send_slice(&[0xff; 67], REMOTE_IPV4.into()),
  643. Err(SendError::BufferFull)
  644. );
  645. assert!(socket.can_send());
  646. let mut bytes = [0xff; 24];
  647. let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
  648. ECHOV4_REPR.emit(&mut packet, &checksum);
  649. assert_eq!(
  650. socket.send_slice(&*packet.into_inner(), REMOTE_IPV4.into()),
  651. Ok(())
  652. );
  653. assert_eq!(
  654. socket.send_slice(b"123456", REMOTE_IPV4.into()),
  655. Err(SendError::BufferFull)
  656. );
  657. assert!(!socket.can_send());
  658. assert_eq!(
  659. socket.dispatch(cx, |_, (ip_repr, icmp_repr)| {
  660. assert_eq!(ip_repr, LOCAL_IPV4_REPR);
  661. assert_eq!(icmp_repr, ECHOV4_REPR.into());
  662. Err(())
  663. }),
  664. Err(())
  665. );
  666. // buffer is not taken off of the tx queue due to the error
  667. assert!(!socket.can_send());
  668. assert_eq!(
  669. socket.dispatch(cx, |_, (ip_repr, icmp_repr)| {
  670. assert_eq!(ip_repr, LOCAL_IPV4_REPR);
  671. assert_eq!(icmp_repr, ECHOV4_REPR.into());
  672. Ok::<_, ()>(())
  673. }),
  674. Ok(())
  675. );
  676. // buffer is taken off of the queue this time
  677. assert!(socket.can_send());
  678. }
  679. #[rstest]
  680. #[case::ethernet(Medium::Ethernet)]
  681. #[cfg(feature = "medium-ethernet")]
  682. fn test_set_hop_limit_v4(#[case] medium: Medium) {
  683. let (mut iface, _, _) = setup(medium);
  684. let cx = iface.context();
  685. let mut s = socket(buffer(0), buffer(1));
  686. let checksum = ChecksumCapabilities::default();
  687. let mut bytes = [0xff; 24];
  688. let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
  689. ECHOV4_REPR.emit(&mut packet, &checksum);
  690. s.set_hop_limit(Some(0x2a));
  691. assert_eq!(
  692. s.send_slice(&*packet.into_inner(), REMOTE_IPV4.into()),
  693. Ok(())
  694. );
  695. assert_eq!(
  696. s.dispatch(cx, |_, (ip_repr, _)| {
  697. assert_eq!(
  698. ip_repr,
  699. IpRepr::Ipv4(Ipv4Repr {
  700. src_addr: LOCAL_IPV4,
  701. dst_addr: REMOTE_IPV4,
  702. next_header: IpProtocol::Icmp,
  703. payload_len: ECHOV4_REPR.buffer_len(),
  704. hop_limit: 0x2a,
  705. })
  706. );
  707. Ok::<_, ()>(())
  708. }),
  709. Ok(())
  710. );
  711. }
  712. #[rstest]
  713. #[case::ethernet(Medium::Ethernet)]
  714. #[cfg(feature = "medium-ethernet")]
  715. fn test_recv_process(#[case] medium: Medium) {
  716. let (mut iface, _, _) = setup(medium);
  717. let cx = iface.context();
  718. let mut socket = socket(buffer(1), buffer(1));
  719. assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
  720. assert!(!socket.can_recv());
  721. assert_eq!(socket.recv(), Err(RecvError::Exhausted));
  722. let checksum = ChecksumCapabilities::default();
  723. let mut bytes = [0xff; 24];
  724. let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]);
  725. ECHOV4_REPR.emit(&mut packet, &checksum);
  726. let data = &*packet.into_inner();
  727. assert!(socket.accepts(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()));
  728. socket.process(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into());
  729. assert!(socket.can_recv());
  730. assert!(socket.accepts(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()));
  731. socket.process(cx, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into());
  732. assert_eq!(socket.recv(), Ok((data, REMOTE_IPV4.into())));
  733. assert!(!socket.can_recv());
  734. }
  735. #[rstest]
  736. #[case::ethernet(Medium::Ethernet)]
  737. #[cfg(feature = "medium-ethernet")]
  738. fn test_accept_bad_id(#[case] medium: Medium) {
  739. let (mut iface, _, _) = setup(medium);
  740. let cx = iface.context();
  741. let mut socket = socket(buffer(1), buffer(1));
  742. assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
  743. let checksum = ChecksumCapabilities::default();
  744. let mut bytes = [0xff; 20];
  745. let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
  746. let icmp_repr = Icmpv4Repr::EchoRequest {
  747. ident: 0x4321,
  748. seq_no: 0x5678,
  749. data: &[0xff; 16],
  750. };
  751. icmp_repr.emit(&mut packet, &checksum);
  752. // Ensure that a packet with an identifier that isn't the bound
  753. // ID is not accepted
  754. assert!(!socket.accepts(cx, &REMOTE_IPV4_REPR, &icmp_repr.into()));
  755. }
  756. #[rstest]
  757. #[case::ethernet(Medium::Ethernet)]
  758. #[cfg(feature = "medium-ethernet")]
  759. fn test_accepts_udp(#[case] medium: Medium) {
  760. let (mut iface, _, _) = setup(medium);
  761. let cx = iface.context();
  762. let mut socket = socket(buffer(1), buffer(1));
  763. assert_eq!(socket.bind(Endpoint::Udp(LOCAL_END_V4.into())), Ok(()));
  764. let checksum = ChecksumCapabilities::default();
  765. let mut bytes = [0xff; 18];
  766. let mut packet = UdpPacket::new_unchecked(&mut bytes);
  767. UDP_REPR.emit(
  768. &mut packet,
  769. &REMOTE_IPV4.into(),
  770. &LOCAL_IPV4.into(),
  771. UDP_PAYLOAD.len(),
  772. |buf| buf.copy_from_slice(UDP_PAYLOAD),
  773. &checksum,
  774. );
  775. let data = &*packet.into_inner();
  776. let icmp_repr = Icmpv4Repr::DstUnreachable {
  777. reason: Icmpv4DstUnreachable::PortUnreachable,
  778. header: Ipv4Repr {
  779. src_addr: LOCAL_IPV4,
  780. dst_addr: REMOTE_IPV4,
  781. next_header: IpProtocol::Icmp,
  782. payload_len: 12,
  783. hop_limit: 0x40,
  784. },
  785. data,
  786. };
  787. let ip_repr = IpRepr::Ipv4(Ipv4Repr {
  788. src_addr: REMOTE_IPV4,
  789. dst_addr: LOCAL_IPV4,
  790. next_header: IpProtocol::Icmp,
  791. payload_len: icmp_repr.buffer_len(),
  792. hop_limit: 0x40,
  793. });
  794. assert!(!socket.can_recv());
  795. // Ensure we can accept ICMP error response to the bound
  796. // UDP port
  797. assert!(socket.accepts(cx, &ip_repr, &icmp_repr.into()));
  798. socket.process(cx, &ip_repr, &icmp_repr.into());
  799. assert!(socket.can_recv());
  800. let mut bytes = [0x00; 46];
  801. let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]);
  802. icmp_repr.emit(&mut packet, &checksum);
  803. assert_eq!(
  804. socket.recv(),
  805. Ok((&*packet.into_inner(), REMOTE_IPV4.into()))
  806. );
  807. assert!(!socket.can_recv());
  808. }
  809. }
  810. #[cfg(all(test, feature = "proto-ipv6"))]
  811. mod test_ipv6 {
  812. use crate::phy::Medium;
  813. use crate::tests::setup;
  814. use rstest::*;
  815. use super::tests_common::*;
  816. use crate::wire::{Icmpv6DstUnreachable, IpEndpoint, Ipv6Address};
  817. const REMOTE_IPV6: Ipv6Address =
  818. Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
  819. const LOCAL_IPV6: Ipv6Address =
  820. Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
  821. const LOCAL_END_V6: IpEndpoint = IpEndpoint {
  822. addr: IpAddress::Ipv6(LOCAL_IPV6),
  823. port: LOCAL_PORT,
  824. };
  825. static ECHOV6_REPR: Icmpv6Repr = Icmpv6Repr::EchoRequest {
  826. ident: 0x1234,
  827. seq_no: 0x5678,
  828. data: &[0xff; 16],
  829. };
  830. static LOCAL_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
  831. src_addr: LOCAL_IPV6,
  832. dst_addr: REMOTE_IPV6,
  833. next_header: IpProtocol::Icmpv6,
  834. payload_len: 24,
  835. hop_limit: 0x40,
  836. });
  837. static REMOTE_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
  838. src_addr: REMOTE_IPV6,
  839. dst_addr: LOCAL_IPV6,
  840. next_header: IpProtocol::Icmpv6,
  841. payload_len: 24,
  842. hop_limit: 0x40,
  843. });
  844. #[test]
  845. fn test_send_unaddressable() {
  846. let mut socket = socket(buffer(0), buffer(1));
  847. assert_eq!(
  848. socket.send_slice(b"abcdef", IpAddress::Ipv6(Ipv6Address::default())),
  849. Err(SendError::Unaddressable)
  850. );
  851. assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV6.into()), Ok(()));
  852. }
  853. #[rstest]
  854. #[case::ethernet(Medium::Ethernet)]
  855. #[cfg(feature = "medium-ethernet")]
  856. fn test_send_dispatch(#[case] medium: Medium) {
  857. let (mut iface, _, _) = setup(medium);
  858. let cx = iface.context();
  859. let mut socket = socket(buffer(0), buffer(1));
  860. let checksum = ChecksumCapabilities::default();
  861. assert_eq!(socket.dispatch(cx, |_, _| unreachable!()), Ok::<_, ()>(()));
  862. // This buffer is too long
  863. assert_eq!(
  864. socket.send_slice(&[0xff; 67], REMOTE_IPV6.into()),
  865. Err(SendError::BufferFull)
  866. );
  867. assert!(socket.can_send());
  868. let mut bytes = vec![0xff; 24];
  869. let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
  870. ECHOV6_REPR.emit(
  871. &LOCAL_IPV6.into(),
  872. &REMOTE_IPV6.into(),
  873. &mut packet,
  874. &checksum,
  875. );
  876. assert_eq!(
  877. socket.send_slice(&*packet.into_inner(), REMOTE_IPV6.into()),
  878. Ok(())
  879. );
  880. assert_eq!(
  881. socket.send_slice(b"123456", REMOTE_IPV6.into()),
  882. Err(SendError::BufferFull)
  883. );
  884. assert!(!socket.can_send());
  885. assert_eq!(
  886. socket.dispatch(cx, |_, (ip_repr, icmp_repr)| {
  887. assert_eq!(ip_repr, LOCAL_IPV6_REPR);
  888. assert_eq!(icmp_repr, ECHOV6_REPR.into());
  889. Err(())
  890. }),
  891. Err(())
  892. );
  893. // buffer is not taken off of the tx queue due to the error
  894. assert!(!socket.can_send());
  895. assert_eq!(
  896. socket.dispatch(cx, |_, (ip_repr, icmp_repr)| {
  897. assert_eq!(ip_repr, LOCAL_IPV6_REPR);
  898. assert_eq!(icmp_repr, ECHOV6_REPR.into());
  899. Ok::<_, ()>(())
  900. }),
  901. Ok(())
  902. );
  903. // buffer is taken off of the queue this time
  904. assert!(socket.can_send());
  905. }
  906. #[rstest]
  907. #[case::ethernet(Medium::Ethernet)]
  908. #[cfg(feature = "medium-ethernet")]
  909. fn test_set_hop_limit(#[case] medium: Medium) {
  910. let (mut iface, _, _) = setup(medium);
  911. let cx = iface.context();
  912. let mut s = socket(buffer(0), buffer(1));
  913. let checksum = ChecksumCapabilities::default();
  914. let mut bytes = vec![0xff; 24];
  915. let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
  916. ECHOV6_REPR.emit(
  917. &LOCAL_IPV6.into(),
  918. &REMOTE_IPV6.into(),
  919. &mut packet,
  920. &checksum,
  921. );
  922. s.set_hop_limit(Some(0x2a));
  923. assert_eq!(
  924. s.send_slice(&*packet.into_inner(), REMOTE_IPV6.into()),
  925. Ok(())
  926. );
  927. assert_eq!(
  928. s.dispatch(cx, |_, (ip_repr, _)| {
  929. assert_eq!(
  930. ip_repr,
  931. IpRepr::Ipv6(Ipv6Repr {
  932. src_addr: LOCAL_IPV6,
  933. dst_addr: REMOTE_IPV6,
  934. next_header: IpProtocol::Icmpv6,
  935. payload_len: ECHOV6_REPR.buffer_len(),
  936. hop_limit: 0x2a,
  937. })
  938. );
  939. Ok::<_, ()>(())
  940. }),
  941. Ok(())
  942. );
  943. }
  944. #[rstest]
  945. #[case::ethernet(Medium::Ethernet)]
  946. #[cfg(feature = "medium-ethernet")]
  947. fn test_recv_process(#[case] medium: Medium) {
  948. let (mut iface, _, _) = setup(medium);
  949. let cx = iface.context();
  950. let mut socket = socket(buffer(1), buffer(1));
  951. assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
  952. assert!(!socket.can_recv());
  953. assert_eq!(socket.recv(), Err(RecvError::Exhausted));
  954. let checksum = ChecksumCapabilities::default();
  955. let mut bytes = [0xff; 24];
  956. let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]);
  957. ECHOV6_REPR.emit(
  958. &LOCAL_IPV6.into(),
  959. &REMOTE_IPV6.into(),
  960. &mut packet,
  961. &checksum,
  962. );
  963. let data = &*packet.into_inner();
  964. assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
  965. socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into());
  966. assert!(socket.can_recv());
  967. assert!(socket.accepts(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
  968. socket.process(cx, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into());
  969. assert_eq!(socket.recv(), Ok((data, REMOTE_IPV6.into())));
  970. assert!(!socket.can_recv());
  971. }
  972. #[rstest]
  973. #[case::ethernet(Medium::Ethernet)]
  974. #[cfg(feature = "medium-ethernet")]
  975. fn test_accept_bad_id(#[case] medium: Medium) {
  976. let (mut iface, _, _) = setup(medium);
  977. let cx = iface.context();
  978. let mut socket = socket(buffer(1), buffer(1));
  979. assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
  980. let checksum = ChecksumCapabilities::default();
  981. let mut bytes = [0xff; 20];
  982. let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
  983. let icmp_repr = Icmpv6Repr::EchoRequest {
  984. ident: 0x4321,
  985. seq_no: 0x5678,
  986. data: &[0xff; 16],
  987. };
  988. icmp_repr.emit(
  989. &LOCAL_IPV6.into(),
  990. &REMOTE_IPV6.into(),
  991. &mut packet,
  992. &checksum,
  993. );
  994. // Ensure that a packet with an identifier that isn't the bound
  995. // ID is not accepted
  996. assert!(!socket.accepts(cx, &REMOTE_IPV6_REPR, &icmp_repr.into()));
  997. }
  998. #[rstest]
  999. #[case::ethernet(Medium::Ethernet)]
  1000. #[cfg(feature = "medium-ethernet")]
  1001. fn test_accepts_udp(#[case] medium: Medium) {
  1002. let (mut iface, _, _) = setup(medium);
  1003. let cx = iface.context();
  1004. let mut socket = socket(buffer(1), buffer(1));
  1005. assert_eq!(socket.bind(Endpoint::Udp(LOCAL_END_V6.into())), Ok(()));
  1006. let checksum = ChecksumCapabilities::default();
  1007. let mut bytes = [0xff; 18];
  1008. let mut packet = UdpPacket::new_unchecked(&mut bytes);
  1009. UDP_REPR.emit(
  1010. &mut packet,
  1011. &REMOTE_IPV6.into(),
  1012. &LOCAL_IPV6.into(),
  1013. UDP_PAYLOAD.len(),
  1014. |buf| buf.copy_from_slice(UDP_PAYLOAD),
  1015. &checksum,
  1016. );
  1017. let data = &*packet.into_inner();
  1018. let icmp_repr = Icmpv6Repr::DstUnreachable {
  1019. reason: Icmpv6DstUnreachable::PortUnreachable,
  1020. header: Ipv6Repr {
  1021. src_addr: LOCAL_IPV6,
  1022. dst_addr: REMOTE_IPV6,
  1023. next_header: IpProtocol::Icmpv6,
  1024. payload_len: 12,
  1025. hop_limit: 0x40,
  1026. },
  1027. data,
  1028. };
  1029. let ip_repr = IpRepr::Ipv6(Ipv6Repr {
  1030. src_addr: REMOTE_IPV6,
  1031. dst_addr: LOCAL_IPV6,
  1032. next_header: IpProtocol::Icmpv6,
  1033. payload_len: icmp_repr.buffer_len(),
  1034. hop_limit: 0x40,
  1035. });
  1036. assert!(!socket.can_recv());
  1037. // Ensure we can accept ICMP error response to the bound
  1038. // UDP port
  1039. assert!(socket.accepts(cx, &ip_repr, &icmp_repr.into()));
  1040. socket.process(cx, &ip_repr, &icmp_repr.into());
  1041. assert!(socket.can_recv());
  1042. let mut bytes = [0x00; 66];
  1043. let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]);
  1044. icmp_repr.emit(
  1045. &LOCAL_IPV6.into(),
  1046. &REMOTE_IPV6.into(),
  1047. &mut packet,
  1048. &checksum,
  1049. );
  1050. assert_eq!(
  1051. socket.recv(),
  1052. Ok((&*packet.into_inner(), REMOTE_IPV6.into()))
  1053. );
  1054. assert!(!socket.can_recv());
  1055. }
  1056. }