icmp.rs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. use core::cmp;
  2. use {Error, Result};
  3. use phy::{ChecksumCapabilities, DeviceCapabilities};
  4. use socket::{Socket, SocketMeta, SocketHandle, PollAt};
  5. use storage::{PacketBuffer, PacketMetadata};
  6. use wire::{IpAddress, IpEndpoint, IpProtocol, IpRepr};
  7. #[cfg(feature = "proto-ipv4")]
  8. use wire::{Ipv4Address, Ipv4Repr, Icmpv4Packet, Icmpv4Repr};
  9. #[cfg(feature = "proto-ipv6")]
  10. use wire::{Ipv6Address, Ipv6Repr, Icmpv6Packet, Icmpv6Repr};
  11. use wire::IcmpRepr;
  12. use wire::{UdpPacket, UdpRepr};
  13. /// Type of endpoint to bind the ICMP socket to. See [IcmpSocket::bind] for
  14. /// more details.
  15. ///
  16. /// [IcmpSocket::bind]: struct.IcmpSocket.html#method.bind
  17. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
  18. pub enum Endpoint {
  19. Unspecified,
  20. Ident(u16),
  21. Udp(IpEndpoint)
  22. }
  23. impl Endpoint {
  24. pub fn is_specified(&self) -> bool {
  25. match *self {
  26. Endpoint::Ident(_) => true,
  27. Endpoint::Udp(endpoint) => endpoint.port != 0,
  28. Endpoint::Unspecified => false
  29. }
  30. }
  31. }
  32. impl Default for Endpoint {
  33. fn default() -> Endpoint { Endpoint::Unspecified }
  34. }
  35. /// An ICMP packet metadata.
  36. pub type IcmpPacketMetadata = PacketMetadata<IpAddress>;
  37. /// An ICMP packet ring buffer.
  38. pub type IcmpSocketBuffer<'a, 'b> = PacketBuffer<'a, 'b, IpAddress>;
  39. /// A ICMP socket
  40. ///
  41. /// An ICMP socket is bound to a specific [IcmpEndpoint] which may
  42. /// be a sepecific UDP port to listen for ICMP error messages related
  43. /// to the port or a specific ICMP identifier value. See [bind] for
  44. /// more details.
  45. ///
  46. /// [IcmpEndpoint]: enum.IcmpEndpoint.html
  47. /// [bind]: #method.bind
  48. #[derive(Debug)]
  49. pub struct IcmpSocket<'a, 'b: 'a> {
  50. pub(crate) meta: SocketMeta,
  51. rx_buffer: IcmpSocketBuffer<'a, 'b>,
  52. tx_buffer: IcmpSocketBuffer<'a, 'b>,
  53. /// The endpoint this socket is communicating with
  54. endpoint: Endpoint,
  55. /// The time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
  56. hop_limit: Option<u8>
  57. }
  58. impl<'a, 'b> IcmpSocket<'a, 'b> {
  59. /// Create an ICMP socket with the given buffers.
  60. pub fn new(rx_buffer: IcmpSocketBuffer<'a, 'b>,
  61. tx_buffer: IcmpSocketBuffer<'a, 'b>) -> IcmpSocket<'a, 'b> {
  62. IcmpSocket {
  63. meta: SocketMeta::default(),
  64. rx_buffer: rx_buffer,
  65. tx_buffer: tx_buffer,
  66. endpoint: Endpoint::default(),
  67. hop_limit: None
  68. }
  69. }
  70. /// Return the socket handle.
  71. #[inline]
  72. pub fn handle(&self) -> SocketHandle {
  73. self.meta.handle
  74. }
  75. /// Return the time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
  76. ///
  77. /// See also the [set_hop_limit](#method.set_hop_limit) method
  78. pub fn hop_limit(&self) -> Option<u8> {
  79. self.hop_limit
  80. }
  81. /// Set the time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
  82. ///
  83. /// A socket without an explicitly set hop limit value uses the default [IANA recommended]
  84. /// value (64).
  85. ///
  86. /// # Panics
  87. ///
  88. /// This function panics if a hop limit value of 0 is given. See [RFC 1122 § 3.2.1.7].
  89. ///
  90. /// [IANA recommended]: https://www.iana.org/assignments/ip-parameters/ip-parameters.xhtml
  91. /// [RFC 1122 § 3.2.1.7]: https://tools.ietf.org/html/rfc1122#section-3.2.1.7
  92. pub fn set_hop_limit(&mut self, hop_limit: Option<u8>) {
  93. // A host MUST NOT send a datagram with a hop limit value of 0
  94. if let Some(0) = hop_limit {
  95. panic!("the time-to-live value of a packet must not be zero")
  96. }
  97. self.hop_limit = hop_limit
  98. }
  99. /// Bind the socket to the given endpoint.
  100. ///
  101. /// This function returns `Err(Error::Illegal)` if the socket was open
  102. /// (see [is_open](#method.is_open)), and `Err(Error::Unaddressable)`
  103. /// if `endpoint` is unspecified (see [is_specified]).
  104. ///
  105. /// # Examples
  106. ///
  107. /// ## Bind to ICMP Error messages associated with a specific UDP port:
  108. ///
  109. /// To [recv] ICMP error messages that are associated with a specific local
  110. /// UDP port, the socket may be bound to a given port using [IcmpEndpoint::Udp].
  111. /// This may be useful for applications using UDP attempting to detect and/or
  112. /// diagnose connection problems.
  113. ///
  114. /// ```
  115. /// # use smoltcp::socket::{Socket, IcmpSocket, IcmpSocketBuffer, IcmpPacketMetadata};
  116. /// # let rx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 20]);
  117. /// # let tx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 20]);
  118. /// use smoltcp::wire::IpEndpoint;
  119. /// use smoltcp::socket::IcmpEndpoint;
  120. ///
  121. /// let mut icmp_socket = // ...
  122. /// # IcmpSocket::new(rx_buffer, tx_buffer);
  123. ///
  124. /// // Bind to ICMP error responses for UDP packets sent from port 53.
  125. /// let endpoint = IpEndpoint::from(53);
  126. /// icmp_socket.bind(IcmpEndpoint::Udp(endpoint)).unwrap();
  127. /// ```
  128. ///
  129. /// ## Bind to a specific ICMP identifier:
  130. ///
  131. /// To [send] and [recv] ICMP packets that are not associated with a specific UDP
  132. /// port, the socket may be bound to a specific ICMP identifier using
  133. /// [IcmpEndpoint::Ident]. This is useful for sending and receiving Echo Request/Reply
  134. /// messages.
  135. ///
  136. /// ```
  137. /// # use smoltcp::socket::{Socket, IcmpSocket, IcmpSocketBuffer, IcmpPacketMetadata};
  138. /// # let rx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 20]);
  139. /// # let tx_buffer = IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY], vec![0; 20]);
  140. /// use smoltcp::socket::IcmpEndpoint;
  141. ///
  142. /// let mut icmp_socket = // ...
  143. /// # IcmpSocket::new(rx_buffer, tx_buffer);
  144. ///
  145. /// // Bind to ICMP messages with the ICMP identifier 0x1234
  146. /// icmp_socket.bind(IcmpEndpoint::Ident(0x1234)).unwrap();
  147. /// ```
  148. ///
  149. /// [is_specified]: enum.IcmpEndpoint.html#method.is_specified
  150. /// [IcmpEndpoint::Ident]: enum.IcmpEndpoint.html#variant.Ident
  151. /// [IcmpEndpoint::Udp]: enum.IcmpEndpoint.html#variant.Udp
  152. /// [send]: #method.send
  153. /// [recv]: #method.recv
  154. pub fn bind<T: Into<Endpoint>>(&mut self, endpoint: T) -> Result<()> {
  155. let endpoint = endpoint.into();
  156. if !endpoint.is_specified() {
  157. return Err(Error::Unaddressable);
  158. }
  159. if self.is_open() { return Err(Error::Illegal) }
  160. self.endpoint = endpoint;
  161. Ok(())
  162. }
  163. /// Check whether the transmit buffer is full.
  164. #[inline]
  165. pub fn can_send(&self) -> bool {
  166. !self.tx_buffer.is_full()
  167. }
  168. /// Check whether the receive buffer is not empty.
  169. #[inline]
  170. pub fn can_recv(&self) -> bool {
  171. !self.rx_buffer.is_empty()
  172. }
  173. /// Return the maximum number packets the socket can receive.
  174. #[inline]
  175. pub fn packet_recv_capacity(&self) -> usize {
  176. self.rx_buffer.packet_capacity()
  177. }
  178. /// Return the maximum number packets the socket can transmit.
  179. #[inline]
  180. pub fn packet_send_capacity(&self) -> usize {
  181. self.tx_buffer.packet_capacity()
  182. }
  183. /// Return the maximum number of bytes inside the recv buffer.
  184. #[inline]
  185. pub fn payload_recv_capacity(&self) -> usize {
  186. self.rx_buffer.payload_capacity()
  187. }
  188. /// Return the maximum number of bytes inside the transmit buffer.
  189. #[inline]
  190. pub fn payload_send_capacity(&self) -> usize {
  191. self.tx_buffer.payload_capacity()
  192. }
  193. /// Check whether the socket is open.
  194. #[inline]
  195. pub fn is_open(&self) -> bool {
  196. self.endpoint != Endpoint::Unspecified
  197. }
  198. /// Enqueue a packet to be sent to a given remote address, and return a pointer
  199. /// to its payload.
  200. ///
  201. /// This function returns `Err(Error::Exhausted)` if the transmit buffer is full,
  202. /// `Err(Error::Truncated)` if the requested size is larger than the packet buffer
  203. /// size, and `Err(Error::Unaddressable)` if the remote address is unspecified.
  204. pub fn send(&mut self, size: usize, endpoint: IpAddress) -> Result<&mut [u8]> {
  205. if endpoint.is_unspecified() {
  206. return Err(Error::Unaddressable)
  207. }
  208. let packet_buf = self.tx_buffer.enqueue(size, endpoint)?;
  209. net_trace!("{}:{}: buffer to send {} octets",
  210. self.meta.handle, endpoint, size);
  211. Ok(packet_buf)
  212. }
  213. /// Enqueue a packet to be sent to a given remote address, and fill it from a slice.
  214. ///
  215. /// See also [send](#method.send).
  216. pub fn send_slice(&mut self, data: &[u8], endpoint: IpAddress) -> Result<()> {
  217. let packet_buf = self.send(data.len(), endpoint)?;
  218. packet_buf.copy_from_slice(data);
  219. Ok(())
  220. }
  221. /// Dequeue a packet received from a remote endpoint, and return the `IpAddress` as well
  222. /// as a pointer to the payload.
  223. ///
  224. /// This function returns `Err(Error::Exhausted)` if the receive buffer is empty.
  225. pub fn recv(&mut self) -> Result<(&[u8], IpAddress)> {
  226. let (endpoint, packet_buf) = self.rx_buffer.dequeue()?;
  227. net_trace!("{}:{}: receive {} buffered octets",
  228. self.meta.handle, endpoint, packet_buf.len());
  229. Ok((packet_buf, endpoint))
  230. }
  231. /// Dequeue a packet received from a remote endpoint, copy the payload into the given slice,
  232. /// and return the amount of octets copied as well as the `IpAddress`
  233. ///
  234. /// See also [recv](#method.recv).
  235. pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<(usize, IpAddress)> {
  236. let (buffer, endpoint) = self.recv()?;
  237. let length = cmp::min(data.len(), buffer.len());
  238. data[..length].copy_from_slice(&buffer[..length]);
  239. Ok((length, endpoint))
  240. }
  241. /// Filter determining which packets received by the interface are appended to
  242. /// the given sockets received buffer.
  243. pub(crate) fn accepts(&self, ip_repr: &IpRepr, icmp_repr: &IcmpRepr,
  244. cksum: &ChecksumCapabilities) -> bool {
  245. match (&self.endpoint, icmp_repr) {
  246. // If we are bound to ICMP errors associated to a UDP port, only
  247. // accept Destination Unreachable messages with the data containing
  248. // a UDP packet send from the local port we are bound to.
  249. #[cfg(feature = "proto-ipv4")]
  250. (&Endpoint::Udp(endpoint), &IcmpRepr::Ipv4(Icmpv4Repr::DstUnreachable { data, .. }))
  251. if endpoint.addr.is_unspecified() || endpoint.addr == ip_repr.dst_addr() => {
  252. let packet = UdpPacket::new_unchecked(data);
  253. match UdpRepr::parse(&packet, &ip_repr.src_addr(), &ip_repr.dst_addr(), cksum) {
  254. Ok(repr) => endpoint.port == repr.src_port,
  255. Err(_) => false,
  256. }
  257. }
  258. #[cfg(feature = "proto-ipv6")]
  259. (&Endpoint::Udp(endpoint), &IcmpRepr::Ipv6(Icmpv6Repr::DstUnreachable { data, .. }))
  260. if endpoint.addr.is_unspecified() || endpoint.addr == ip_repr.dst_addr() => {
  261. let packet = UdpPacket::new_unchecked(data);
  262. match UdpRepr::parse(&packet, &ip_repr.src_addr(), &ip_repr.dst_addr(), cksum) {
  263. Ok(repr) => endpoint.port == repr.src_port,
  264. Err(_) => false,
  265. }
  266. }
  267. // If we are bound to a specific ICMP identifier value, only accept an
  268. // Echo Request/Reply with the identifier field matching the endpoint
  269. // port.
  270. #[cfg(feature = "proto-ipv4")]
  271. (&Endpoint::Ident(bound_ident),
  272. &IcmpRepr::Ipv4(Icmpv4Repr::EchoRequest { ident, .. })) |
  273. (&Endpoint::Ident(bound_ident),
  274. &IcmpRepr::Ipv4(Icmpv4Repr::EchoReply { ident, .. })) =>
  275. ident == bound_ident,
  276. #[cfg(feature = "proto-ipv6")]
  277. (&Endpoint::Ident(bound_ident),
  278. &IcmpRepr::Ipv6(Icmpv6Repr::EchoRequest { ident, .. })) |
  279. (&Endpoint::Ident(bound_ident),
  280. &IcmpRepr::Ipv6(Icmpv6Repr::EchoReply { ident, .. })) =>
  281. ident == bound_ident,
  282. _ => false,
  283. }
  284. }
  285. pub(crate) fn process(&mut self, ip_repr: &IpRepr, icmp_repr: &IcmpRepr,
  286. _cksum: &ChecksumCapabilities) -> Result<()> {
  287. match icmp_repr {
  288. #[cfg(feature = "proto-ipv4")]
  289. &IcmpRepr::Ipv4(ref icmp_repr) => {
  290. let packet_buf = self.rx_buffer.enqueue(icmp_repr.buffer_len(),
  291. ip_repr.src_addr())?;
  292. icmp_repr.emit(&mut Icmpv4Packet::new_unchecked(packet_buf),
  293. &ChecksumCapabilities::default());
  294. net_trace!("{}:{}: receiving {} octets",
  295. self.meta.handle, icmp_repr.buffer_len(), packet_buf.len());
  296. },
  297. #[cfg(feature = "proto-ipv6")]
  298. &IcmpRepr::Ipv6(ref icmp_repr) => {
  299. let packet_buf = self.rx_buffer.enqueue(icmp_repr.buffer_len(),
  300. ip_repr.src_addr())?;
  301. icmp_repr.emit(&ip_repr.src_addr(), &ip_repr.dst_addr(),
  302. &mut Icmpv6Packet::new_unchecked(packet_buf),
  303. &ChecksumCapabilities::default());
  304. net_trace!("{}:{}: receiving {} octets",
  305. self.meta.handle, icmp_repr.buffer_len(), packet_buf.len());
  306. },
  307. }
  308. Ok(())
  309. }
  310. pub(crate) fn dispatch<F>(&mut self, _caps: &DeviceCapabilities, emit: F) -> Result<()>
  311. where F: FnOnce((IpRepr, IcmpRepr)) -> Result<()>
  312. {
  313. let handle = self.meta.handle;
  314. let hop_limit = self.hop_limit.unwrap_or(64);
  315. self.tx_buffer.dequeue_with(|remote_endpoint, packet_buf| {
  316. net_trace!("{}:{}: sending {} octets",
  317. handle, remote_endpoint, packet_buf.len());
  318. match *remote_endpoint {
  319. #[cfg(feature = "proto-ipv4")]
  320. IpAddress::Ipv4(ipv4_addr) => {
  321. let packet = Icmpv4Packet::new_unchecked(&*packet_buf);
  322. let repr = Icmpv4Repr::parse(&packet, &ChecksumCapabilities::ignored())?;
  323. let ip_repr = IpRepr::Ipv4(Ipv4Repr {
  324. src_addr: Ipv4Address::default(),
  325. dst_addr: ipv4_addr,
  326. protocol: IpProtocol::Icmp,
  327. payload_len: repr.buffer_len(),
  328. hop_limit: hop_limit,
  329. });
  330. emit((ip_repr, IcmpRepr::Ipv4(repr)))
  331. },
  332. #[cfg(feature = "proto-ipv6")]
  333. IpAddress::Ipv6(ipv6_addr) => {
  334. let packet = Icmpv6Packet::new_unchecked(&*packet_buf);
  335. let src_addr = Ipv6Address::default();
  336. let repr = Icmpv6Repr::parse(&src_addr.into(), &ipv6_addr.into(), &packet, &ChecksumCapabilities::ignored())?;
  337. let ip_repr = IpRepr::Ipv6(Ipv6Repr {
  338. src_addr: src_addr,
  339. dst_addr: ipv6_addr,
  340. next_header: IpProtocol::Icmpv6,
  341. payload_len: repr.buffer_len(),
  342. hop_limit: hop_limit,
  343. });
  344. emit((ip_repr, IcmpRepr::Ipv6(repr)))
  345. },
  346. _ => Err(Error::Unaddressable)
  347. }
  348. })
  349. }
  350. pub(crate) fn poll_at(&self) -> PollAt {
  351. if self.tx_buffer.is_empty() {
  352. PollAt::Ingress
  353. } else {
  354. PollAt::Now
  355. }
  356. }
  357. }
  358. impl<'a, 'b> Into<Socket<'a, 'b>> for IcmpSocket<'a, 'b> {
  359. fn into(self) -> Socket<'a, 'b> {
  360. Socket::Icmp(self)
  361. }
  362. }
  363. #[cfg(test)]
  364. mod tests_common {
  365. pub use phy::DeviceCapabilities;
  366. pub use wire::IpAddress;
  367. pub use super::*;
  368. pub fn buffer(packets: usize) -> IcmpSocketBuffer<'static, 'static> {
  369. IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY; packets], vec![0; 66 * packets])
  370. }
  371. pub fn socket(rx_buffer: IcmpSocketBuffer<'static, 'static>,
  372. tx_buffer: IcmpSocketBuffer<'static, 'static>) -> IcmpSocket<'static, 'static> {
  373. IcmpSocket::new(rx_buffer, tx_buffer)
  374. }
  375. pub const LOCAL_PORT: u16 = 53;
  376. pub static UDP_REPR: UdpRepr = UdpRepr {
  377. src_port: 53,
  378. dst_port: 9090,
  379. payload: &[0xff; 10]
  380. };
  381. }
  382. #[cfg(all(test, feature = "proto-ipv4"))]
  383. mod test_ipv4 {
  384. use super::tests_common::*;
  385. use wire::Icmpv4DstUnreachable;
  386. const REMOTE_IPV4: Ipv4Address = Ipv4Address([0x7f, 0x00, 0x00, 0x02]);
  387. const LOCAL_IPV4: Ipv4Address = Ipv4Address([0x7f, 0x00, 0x00, 0x01]);
  388. const LOCAL_END_V4: IpEndpoint = IpEndpoint { addr: IpAddress::Ipv4(LOCAL_IPV4), port: LOCAL_PORT };
  389. static ECHOV4_REPR: Icmpv4Repr = Icmpv4Repr::EchoRequest {
  390. ident: 0x1234,
  391. seq_no: 0x5678,
  392. data: &[0xff; 16]
  393. };
  394. static LOCAL_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr {
  395. src_addr: Ipv4Address::UNSPECIFIED,
  396. dst_addr: REMOTE_IPV4,
  397. protocol: IpProtocol::Icmp,
  398. payload_len: 24,
  399. hop_limit: 0x40
  400. });
  401. static REMOTE_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr {
  402. src_addr: REMOTE_IPV4,
  403. dst_addr: LOCAL_IPV4,
  404. protocol: IpProtocol::Icmp,
  405. payload_len: 24,
  406. hop_limit: 0x40
  407. });
  408. #[test]
  409. fn test_send_unaddressable() {
  410. let mut socket = socket(buffer(0), buffer(1));
  411. assert_eq!(socket.send_slice(b"abcdef", IpAddress::default()),
  412. Err(Error::Unaddressable));
  413. assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV4.into()), Ok(()));
  414. }
  415. #[test]
  416. fn test_send_dispatch() {
  417. let mut socket = socket(buffer(0), buffer(1));
  418. let caps = DeviceCapabilities::default();
  419. assert_eq!(socket.dispatch(&caps, |_| unreachable!()),
  420. Err(Error::Exhausted));
  421. // This buffer is too long
  422. assert_eq!(socket.send_slice(&[0xff; 67], REMOTE_IPV4.into()), Err(Error::Truncated));
  423. assert!(socket.can_send());
  424. let mut bytes = [0xff; 24];
  425. let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
  426. ECHOV4_REPR.emit(&mut packet, &caps.checksum);
  427. assert_eq!(socket.send_slice(&packet.into_inner()[..], REMOTE_IPV4.into()), Ok(()));
  428. assert_eq!(socket.send_slice(b"123456", REMOTE_IPV4.into()), Err(Error::Exhausted));
  429. assert!(!socket.can_send());
  430. assert_eq!(socket.dispatch(&caps, |(ip_repr, icmp_repr)| {
  431. assert_eq!(ip_repr, LOCAL_IPV4_REPR);
  432. assert_eq!(icmp_repr, ECHOV4_REPR.into());
  433. Err(Error::Unaddressable)
  434. }), Err(Error::Unaddressable));
  435. // buffer is not taken off of the tx queue due to the error
  436. assert!(!socket.can_send());
  437. assert_eq!(socket.dispatch(&caps, |(ip_repr, icmp_repr)| {
  438. assert_eq!(ip_repr, LOCAL_IPV4_REPR);
  439. assert_eq!(icmp_repr, ECHOV4_REPR.into());
  440. Ok(())
  441. }), Ok(()));
  442. // buffer is taken off of the queue this time
  443. assert!(socket.can_send());
  444. }
  445. #[test]
  446. fn test_set_hop_limit_v4() {
  447. let mut s = socket(buffer(0), buffer(1));
  448. let caps = DeviceCapabilities::default();
  449. let mut bytes = [0xff; 24];
  450. let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
  451. ECHOV4_REPR.emit(&mut packet, &caps.checksum);
  452. s.set_hop_limit(Some(0x2a));
  453. assert_eq!(s.send_slice(&packet.into_inner()[..], REMOTE_IPV4.into()), Ok(()));
  454. assert_eq!(s.dispatch(&caps, |(ip_repr, _)| {
  455. assert_eq!(ip_repr, IpRepr::Ipv4(Ipv4Repr {
  456. src_addr: Ipv4Address::UNSPECIFIED,
  457. dst_addr: REMOTE_IPV4,
  458. protocol: IpProtocol::Icmp,
  459. payload_len: ECHOV4_REPR.buffer_len(),
  460. hop_limit: 0x2a,
  461. }));
  462. Ok(())
  463. }), Ok(()));
  464. }
  465. #[test]
  466. fn test_recv_process() {
  467. let mut socket = socket(buffer(1), buffer(1));
  468. assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
  469. assert!(!socket.can_recv());
  470. assert_eq!(socket.recv(), Err(Error::Exhausted));
  471. let caps = DeviceCapabilities::default();
  472. let mut bytes = [0xff; 24];
  473. let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
  474. ECHOV4_REPR.emit(&mut packet, &caps.checksum);
  475. let data = &packet.into_inner()[..];
  476. assert!(socket.accepts(&REMOTE_IPV4_REPR, &ECHOV4_REPR.into(), &caps.checksum));
  477. assert_eq!(socket.process(&REMOTE_IPV4_REPR, &ECHOV4_REPR.into(), &caps.checksum),
  478. Ok(()));
  479. assert!(socket.can_recv());
  480. assert!(socket.accepts(&REMOTE_IPV4_REPR, &ECHOV4_REPR.into(), &caps.checksum));
  481. assert_eq!(socket.process(&REMOTE_IPV4_REPR, &ECHOV4_REPR.into(), &caps.checksum),
  482. Err(Error::Exhausted));
  483. assert_eq!(socket.recv(), Ok((&data[..], REMOTE_IPV4.into())));
  484. assert!(!socket.can_recv());
  485. }
  486. #[test]
  487. fn test_accept_bad_id() {
  488. let mut socket = socket(buffer(1), buffer(1));
  489. assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
  490. let caps = DeviceCapabilities::default();
  491. let mut bytes = [0xff; 20];
  492. let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
  493. let icmp_repr = Icmpv4Repr::EchoRequest {
  494. ident: 0x4321,
  495. seq_no: 0x5678,
  496. data: &[0xff; 16]
  497. };
  498. icmp_repr.emit(&mut packet, &caps.checksum);
  499. // Ensure that a packet with an identifier that isn't the bound
  500. // ID is not accepted
  501. assert!(!socket.accepts(&REMOTE_IPV4_REPR, &icmp_repr.into(), &caps.checksum));
  502. }
  503. #[test]
  504. fn test_accepts_udp() {
  505. let mut socket = socket(buffer(1), buffer(1));
  506. assert_eq!(socket.bind(Endpoint::Udp(LOCAL_END_V4)), Ok(()));
  507. let caps = DeviceCapabilities::default();
  508. let mut bytes = [0xff; 18];
  509. let mut packet = UdpPacket::new_unchecked(&mut bytes);
  510. UDP_REPR.emit(&mut packet, &REMOTE_IPV4.into(), &LOCAL_IPV4.into(), &caps.checksum);
  511. let data = &packet.into_inner()[..];
  512. let icmp_repr = Icmpv4Repr::DstUnreachable {
  513. reason: Icmpv4DstUnreachable::PortUnreachable,
  514. header: Ipv4Repr {
  515. src_addr: LOCAL_IPV4,
  516. dst_addr: REMOTE_IPV4,
  517. protocol: IpProtocol::Icmp,
  518. payload_len: 12,
  519. hop_limit: 0x40
  520. },
  521. data: data
  522. };
  523. let ip_repr = IpRepr::Unspecified {
  524. src_addr: REMOTE_IPV4.into(),
  525. dst_addr: LOCAL_IPV4.into(),
  526. protocol: IpProtocol::Icmp,
  527. payload_len: icmp_repr.buffer_len(),
  528. hop_limit: 0x40
  529. };
  530. assert!(!socket.can_recv());
  531. // Ensure we can accept ICMP error response to the bound
  532. // UDP port
  533. assert!(socket.accepts(&ip_repr, &icmp_repr.into(), &caps.checksum));
  534. assert_eq!(socket.process(&ip_repr, &icmp_repr.into(), &caps.checksum),
  535. Ok(()));
  536. assert!(socket.can_recv());
  537. let mut bytes = [0x00; 46];
  538. let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]);
  539. icmp_repr.emit(&mut packet, &caps.checksum);
  540. assert_eq!(socket.recv(), Ok((&packet.into_inner()[..], REMOTE_IPV4.into())));
  541. assert!(!socket.can_recv());
  542. }
  543. }
  544. #[cfg(all(test, feature = "proto-ipv6"))]
  545. mod test_ipv6 {
  546. use super::tests_common::*;
  547. use wire::Icmpv6DstUnreachable;
  548. const REMOTE_IPV6: Ipv6Address = Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0,
  549. 0, 0, 0, 0, 0, 0, 0, 1]);
  550. const LOCAL_IPV6: Ipv6Address = Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0,
  551. 0, 0, 0, 0, 0, 0, 0, 2]);
  552. const LOCAL_END_V6: IpEndpoint = IpEndpoint { addr: IpAddress::Ipv6(LOCAL_IPV6), port: LOCAL_PORT };
  553. static ECHOV6_REPR: Icmpv6Repr = Icmpv6Repr::EchoRequest {
  554. ident: 0x1234,
  555. seq_no: 0x5678,
  556. data: &[0xff; 16]
  557. };
  558. static LOCAL_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
  559. src_addr: Ipv6Address::UNSPECIFIED,
  560. dst_addr: REMOTE_IPV6,
  561. next_header: IpProtocol::Icmpv6,
  562. payload_len: 24,
  563. hop_limit: 0x40
  564. });
  565. static REMOTE_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
  566. src_addr: REMOTE_IPV6,
  567. dst_addr: LOCAL_IPV6,
  568. next_header: IpProtocol::Icmpv6,
  569. payload_len: 24,
  570. hop_limit: 0x40
  571. });
  572. #[test]
  573. fn test_send_unaddressable() {
  574. let mut socket = socket(buffer(0), buffer(1));
  575. assert_eq!(socket.send_slice(b"abcdef", IpAddress::default()),
  576. Err(Error::Unaddressable));
  577. assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV6.into()), Ok(()));
  578. }
  579. #[test]
  580. fn test_send_dispatch() {
  581. let mut socket = socket(buffer(0), buffer(1));
  582. let caps = DeviceCapabilities::default();
  583. assert_eq!(socket.dispatch(&caps, |_| unreachable!()),
  584. Err(Error::Exhausted));
  585. // This buffer is too long
  586. assert_eq!(socket.send_slice(&[0xff; 67], REMOTE_IPV6.into()), Err(Error::Truncated));
  587. assert!(socket.can_send());
  588. let mut bytes = vec![0xff; 24];
  589. let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
  590. ECHOV6_REPR.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &caps.checksum);
  591. assert_eq!(socket.send_slice(&packet.into_inner()[..], REMOTE_IPV6.into()), Ok(()));
  592. assert_eq!(socket.send_slice(b"123456", REMOTE_IPV6.into()), Err(Error::Exhausted));
  593. assert!(!socket.can_send());
  594. assert_eq!(socket.dispatch(&caps, |(ip_repr, icmp_repr)| {
  595. assert_eq!(ip_repr, LOCAL_IPV6_REPR);
  596. assert_eq!(icmp_repr, ECHOV6_REPR.into());
  597. Err(Error::Unaddressable)
  598. }), Err(Error::Unaddressable));
  599. // buffer is not taken off of the tx queue due to the error
  600. assert!(!socket.can_send());
  601. assert_eq!(socket.dispatch(&caps, |(ip_repr, icmp_repr)| {
  602. assert_eq!(ip_repr, LOCAL_IPV6_REPR);
  603. assert_eq!(icmp_repr, ECHOV6_REPR.into());
  604. Ok(())
  605. }), Ok(()));
  606. // buffer is taken off of the queue this time
  607. assert!(socket.can_send());
  608. }
  609. #[test]
  610. fn test_set_hop_limit() {
  611. let mut s = socket(buffer(0), buffer(1));
  612. let caps = DeviceCapabilities::default();
  613. let mut bytes = vec![0xff; 24];
  614. let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
  615. ECHOV6_REPR.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &caps.checksum);
  616. s.set_hop_limit(Some(0x2a));
  617. assert_eq!(s.send_slice(&packet.into_inner()[..], REMOTE_IPV6.into()), Ok(()));
  618. assert_eq!(s.dispatch(&caps, |(ip_repr, _)| {
  619. assert_eq!(ip_repr, IpRepr::Ipv6(Ipv6Repr {
  620. src_addr: Ipv6Address::UNSPECIFIED,
  621. dst_addr: REMOTE_IPV6,
  622. next_header: IpProtocol::Icmpv6,
  623. payload_len: ECHOV6_REPR.buffer_len(),
  624. hop_limit: 0x2a,
  625. }));
  626. Ok(())
  627. }), Ok(()));
  628. }
  629. #[test]
  630. fn test_recv_process() {
  631. let mut socket = socket(buffer(1), buffer(1));
  632. assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
  633. assert!(!socket.can_recv());
  634. assert_eq!(socket.recv(), Err(Error::Exhausted));
  635. let caps = DeviceCapabilities::default();
  636. let mut bytes = [0xff; 24];
  637. let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
  638. ECHOV6_REPR.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &caps.checksum);
  639. let data = &packet.into_inner()[..];
  640. assert!(socket.accepts(&REMOTE_IPV6_REPR, &ECHOV6_REPR.into(), &caps.checksum));
  641. assert_eq!(socket.process(&REMOTE_IPV6_REPR, &ECHOV6_REPR.into(), &caps.checksum),
  642. Ok(()));
  643. assert!(socket.can_recv());
  644. assert!(socket.accepts(&REMOTE_IPV6_REPR, &ECHOV6_REPR.into(), &caps.checksum));
  645. assert_eq!(socket.process(&REMOTE_IPV6_REPR, &ECHOV6_REPR.into(), &caps.checksum),
  646. Err(Error::Exhausted));
  647. assert_eq!(socket.recv(), Ok((&data[..], REMOTE_IPV6.into())));
  648. assert!(!socket.can_recv());
  649. }
  650. #[test]
  651. fn test_accept_bad_id() {
  652. let mut socket = socket(buffer(1), buffer(1));
  653. assert_eq!(socket.bind(Endpoint::Ident(0x1234)), Ok(()));
  654. let caps = DeviceCapabilities::default();
  655. let mut bytes = [0xff; 20];
  656. let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
  657. let icmp_repr = Icmpv6Repr::EchoRequest {
  658. ident: 0x4321,
  659. seq_no: 0x5678,
  660. data: &[0xff; 16]
  661. };
  662. icmp_repr.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &caps.checksum);
  663. // Ensure that a packet with an identifier that isn't the bound
  664. // ID is not accepted
  665. assert!(!socket.accepts(&REMOTE_IPV6_REPR, &icmp_repr.into(), &caps.checksum));
  666. }
  667. #[test]
  668. fn test_accepts_udp() {
  669. let mut socket = socket(buffer(1), buffer(1));
  670. assert_eq!(socket.bind(Endpoint::Udp(LOCAL_END_V6)), Ok(()));
  671. let caps = DeviceCapabilities::default();
  672. let mut bytes = [0xff; 18];
  673. let mut packet = UdpPacket::new_unchecked(&mut bytes);
  674. UDP_REPR.emit(&mut packet, &REMOTE_IPV6.into(), &LOCAL_IPV6.into(), &caps.checksum);
  675. let data = &packet.into_inner()[..];
  676. let icmp_repr = Icmpv6Repr::DstUnreachable {
  677. reason: Icmpv6DstUnreachable::PortUnreachable,
  678. header: Ipv6Repr {
  679. src_addr: LOCAL_IPV6,
  680. dst_addr: REMOTE_IPV6,
  681. next_header: IpProtocol::Icmpv6,
  682. payload_len: 12,
  683. hop_limit: 0x40
  684. },
  685. data: data
  686. };
  687. let ip_repr = IpRepr::Unspecified {
  688. src_addr: REMOTE_IPV6.into(),
  689. dst_addr: LOCAL_IPV6.into(),
  690. protocol: IpProtocol::Icmpv6,
  691. payload_len: icmp_repr.buffer_len(),
  692. hop_limit: 0x40
  693. };
  694. assert!(!socket.can_recv());
  695. // Ensure we can accept ICMP error response to the bound
  696. // UDP port
  697. assert!(socket.accepts(&ip_repr, &icmp_repr.into(), &caps.checksum));
  698. assert_eq!(socket.process(&ip_repr, &icmp_repr.into(), &caps.checksum),
  699. Ok(()));
  700. assert!(socket.can_recv());
  701. let mut bytes = [0x00; 66];
  702. let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]);
  703. icmp_repr.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &caps.checksum);
  704. assert_eq!(socket.recv(), Ok((&packet.into_inner()[..], REMOTE_IPV6.into())));
  705. assert!(!socket.can_recv());
  706. }
  707. }