icmp.rs 29 KB

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