From 1cd3625bf4bbe4ca4dc661e68204a1e7efd67723 Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 24 Oct 2017 23:04:33 +0000 Subject: [PATCH] Small adjustments to TTL code; style, docs, and tests. NFCI. --- README.md | 1 + src/socket/tcp.rs | 63 ++++++++++++++++++++++++++++------------------- src/socket/udp.rs | 59 +++++++++++++++++++++++++------------------- 3 files changed, 71 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index d469962..f8452dc 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ The only supported medium is Ethernet. The only supported internetworking protocol is IPv4. * IPv4 header checksum is generated and validated. + * IPv4 time-to-live value is configurable per socket, set to 64 by default. * IPv4 fragmentation is **not** supported. * IPv4 options are **not** supported and are silently ignored. * IPv4 routes or default gateways are **not** supported. diff --git a/src/socket/tcp.rs b/src/socket/tcp.rs index a9f4463..d9a872f 100644 --- a/src/socket/tcp.rs +++ b/src/socket/tcp.rs @@ -324,21 +324,21 @@ impl<'a> TcpSocket<'a> { /// Set the time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets. /// /// A socket without an explicitly set TTL value uses the default [IANA recommended] - /// value (`64`). + /// value (64). /// /// # Panics /// - /// This function panics if a TTL value of `0` is given. See [RFC 1122 § 3.2.1.7]. + /// This function panics if a TTL value of 0 is given. See [RFC 1122 § 3.2.1.7]. /// /// [IANA recommended]: https://www.iana.org/assignments/ip-parameters/ip-parameters.xhtml /// [RFC 1122 § 3.2.1.7]: https://tools.ietf.org/html/rfc1122#section-3.2.1.7 pub fn set_ttl(&mut self, ttl: Option) { - // A host MUST NOT send a datagram with a Time-to-Live (TTL) - // value of 0 - match ttl { - Some(0) => { panic!("A TTL value of 0 is invalid for a sent packet"); }, - catchall => self.ttl = catchall, + // A host MUST NOT send a datagram with a Time-to-Live (TTL) value of 0 + if let Some(0) = ttl { + panic!("the time-to-live value of a packet must not be zero") } + + self.ttl = ttl } /// Return the local endpoint. @@ -3410,6 +3410,36 @@ mod test { })); } + // =========================================================================================// + // Tests for time-to-live configuration. + // =========================================================================================// + + #[test] + fn test_set_ttl() { + let mut s = socket_syn_received(); + let mut caps = DeviceCapabilities::default(); + caps.max_transmission_unit = 1520; + + s.set_ttl(Some(0x2a)); + assert_eq!(s.dispatch(0, &caps, |(ip_repr, _)| { + assert_eq!(ip_repr, IpRepr::Ipv4(Ipv4Repr { + src_addr: Ipv4Address([10, 0, 0, 1]), + dst_addr: Ipv4Address([10, 0, 0, 2]), + protocol: IpProtocol::Tcp, + payload_len: 24, + ttl: 0x2a, + })); + Ok(()) + }), Ok(())); + } + + #[test] + #[should_panic(expected = "the time-to-live value of a packet must not be zero")] + fn test_set_ttl_zero() { + let mut s = socket_syn_received(); + s.set_ttl(Some(0)); + } + // =========================================================================================// // Tests for reassembly. // =========================================================================================// @@ -3530,23 +3560,4 @@ mod test { }; assert!(!s.accepts(&ip_repr_wrong_dst, &tcp_repr)); } - - #[test] - fn test_set_ttl() { - let mut s = socket_syn_received(); - let mut caps = DeviceCapabilities::default(); - caps.max_transmission_unit = 1520; - - s.set_ttl(Some(0x2a)); - assert_eq!(s.dispatch(0, &caps, |(ip_repr, _)| { - assert_eq!(ip_repr, IpRepr::Ipv4(Ipv4Repr { - src_addr: Ipv4Address([10, 0, 0, 1]), - dst_addr: Ipv4Address([10, 0, 0, 2]), - protocol: IpProtocol::Tcp, - payload_len: 24, - ttl: 0x2a, - })); - Ok(()) - }), Ok(())); - } } diff --git a/src/socket/udp.rs b/src/socket/udp.rs index efda8c7..9ffd9b0 100644 --- a/src/socket/udp.rs +++ b/src/socket/udp.rs @@ -107,21 +107,21 @@ impl<'a, 'b> UdpSocket<'a, 'b> { /// Set the time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets. /// /// A socket without an explicitly set TTL value uses the default [IANA recommended] - /// value (`64`). + /// value (64). /// /// # Panics /// - /// This function panics if a TTL value of `0` is given. See [RFC 1122 § 3.2.1.7]. + /// This function panics if a TTL value of 0 is given. See [RFC 1122 § 3.2.1.7]. /// /// [IANA recommended]: https://www.iana.org/assignments/ip-parameters/ip-parameters.xhtml /// [RFC 1122 § 3.2.1.7]: https://tools.ietf.org/html/rfc1122#section-3.2.1.7 pub fn set_ttl(&mut self, ttl: Option) { - // A host MUST NOT send a datagram with a Time-to-Live (TTL) - // value of 0 - match ttl { - Some(0) => { panic!("A TTL value of 0 is invalid for a sent packet"); }, - catchall => self.ttl = catchall, + // A host MUST NOT send a datagram with a Time-to-Live (TTL) value of 0 + if let Some(0) = ttl { + panic!("the time-to-live value of a packet must not be zero") } + + self.ttl = ttl } /// Bind the socket to the given endpoint. @@ -424,6 +424,32 @@ mod test { Err(Error::Truncated)); } + #[test] + fn test_set_ttl() { + let mut s = socket(buffer(0), buffer(1)); + assert_eq!(s.bind(LOCAL_END), Ok(())); + + s.set_ttl(Some(0x2a)); + assert_eq!(s.send_slice(b"abcdef", REMOTE_END), Ok(())); + assert_eq!(s.dispatch(|(ip_repr, _)| { + assert_eq!(ip_repr, IpRepr::Unspecified{ + src_addr: LOCAL_IP, + dst_addr: REMOTE_IP, + protocol: IpProtocol::Udp, + payload_len: 8 + 6, + ttl: 0x2a, + }); + Ok(()) + }), Ok(())); + } + + #[test] + #[should_panic(expected = "the time-to-live value of a packet must not be zero")] + fn test_set_ttl_zero() { + let mut s = socket(buffer(0), buffer(1)); + s.set_ttl(Some(0)); + } + #[test] fn test_doesnt_accept_wrong_port() { let mut socket = socket(buffer(1), buffer(0)); @@ -453,23 +479,4 @@ mod test { assert_eq!(ip_bound_socket.bind(LOCAL_END), Ok(())); assert!(!ip_bound_socket.accepts(&ip_repr, &REMOTE_UDP_REPR)); } - - #[test] - fn test_set_ttl() { - let mut s = socket(buffer(0), buffer(1)); - assert_eq!(s.bind(LOCAL_END), Ok(())); - - s.set_ttl(Some(0x2a)); - assert_eq!(s.send_slice(b"abcdef", REMOTE_END), Ok(())); - assert_eq!(s.dispatch(|(ip_repr, _)| { - assert_eq!(ip_repr, IpRepr::Unspecified{ - src_addr: LOCAL_IP, - dst_addr: REMOTE_IP, - protocol: IpProtocol::Udp, - payload_len: 8 + 6, - ttl: 0x2a, - }); - Ok(()) - }), Ok(())); - } }