Small adjustments to TTL code; style, docs, and tests. NFCI.

This commit is contained in:
whitequark 2017-10-24 23:04:33 +00:00
parent eef65d2676
commit 1cd3625bf4
3 changed files with 71 additions and 52 deletions

View File

@ -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.

View File

@ -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<u8>) {
// 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(()));
}
}

View File

@ -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<u8>) {
// 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(()));
}
}