mirror of
https://github.com/smoltcp-rs/smoltcp.git
synced 2025-10-02 15:15:05 +00:00
Implement set_ttl for Tcp and Udp sockets
- Add the ttl member to the IpRepr - Add the ttl member along with setters and getters to the tcp and udp socket types - Add unit tests for the new set_ttl parameter - Update usage of IpRepr to include the ttl value
This commit is contained in:
parent
7c6cd6b9a3
commit
fea462837d
@ -31,7 +31,6 @@ The only supported medium is Ethernet.
|
|||||||
The only supported internetworking protocol is IPv4.
|
The only supported internetworking protocol is IPv4.
|
||||||
|
|
||||||
* IPv4 header checksum is generated and validated.
|
* IPv4 header checksum is generated and validated.
|
||||||
* IPv4 time-to-live value is fixed at 64.
|
|
||||||
* IPv4 fragmentation is **not** supported.
|
* IPv4 fragmentation is **not** supported.
|
||||||
* IPv4 options are **not** supported and are silently ignored.
|
* IPv4 options are **not** supported and are silently ignored.
|
||||||
* IPv4 routes or default gateways are **not** supported.
|
* IPv4 routes or default gateways are **not** supported.
|
||||||
|
@ -94,6 +94,7 @@ fn main() {
|
|||||||
dst_addr: remote_addr,
|
dst_addr: remote_addr,
|
||||||
protocol: IpProtocol::Icmp,
|
protocol: IpProtocol::Icmp,
|
||||||
payload_len: icmp_repr.buffer_len(),
|
payload_len: icmp_repr.buffer_len(),
|
||||||
|
ttl: 64
|
||||||
};
|
};
|
||||||
|
|
||||||
let raw_payload = socket
|
let raw_payload = socket
|
||||||
|
@ -378,7 +378,8 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
|
|||||||
src_addr: ipv4_repr.dst_addr,
|
src_addr: ipv4_repr.dst_addr,
|
||||||
dst_addr: ipv4_repr.src_addr,
|
dst_addr: ipv4_repr.src_addr,
|
||||||
protocol: IpProtocol::Icmp,
|
protocol: IpProtocol::Icmp,
|
||||||
payload_len: icmp_reply_repr.buffer_len()
|
payload_len: icmp_reply_repr.buffer_len(),
|
||||||
|
ttl: 64,
|
||||||
};
|
};
|
||||||
Ok(Packet::Icmpv4(ipv4_reply_repr, icmp_reply_repr))
|
Ok(Packet::Icmpv4(ipv4_reply_repr, icmp_reply_repr))
|
||||||
}
|
}
|
||||||
@ -403,7 +404,8 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
|
|||||||
src_addr: ipv4_repr.dst_addr,
|
src_addr: ipv4_repr.dst_addr,
|
||||||
dst_addr: ipv4_repr.src_addr,
|
dst_addr: ipv4_repr.src_addr,
|
||||||
protocol: IpProtocol::Icmp,
|
protocol: IpProtocol::Icmp,
|
||||||
payload_len: icmp_reply_repr.buffer_len()
|
payload_len: icmp_reply_repr.buffer_len(),
|
||||||
|
ttl: 64
|
||||||
};
|
};
|
||||||
Ok(Packet::Icmpv4(ipv4_reply_repr, icmp_reply_repr))
|
Ok(Packet::Icmpv4(ipv4_reply_repr, icmp_reply_repr))
|
||||||
}
|
}
|
||||||
@ -448,7 +450,8 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
|
|||||||
src_addr: ipv4_repr.dst_addr,
|
src_addr: ipv4_repr.dst_addr,
|
||||||
dst_addr: ipv4_repr.src_addr,
|
dst_addr: ipv4_repr.src_addr,
|
||||||
protocol: IpProtocol::Icmp,
|
protocol: IpProtocol::Icmp,
|
||||||
payload_len: icmpv4_reply_repr.buffer_len()
|
payload_len: icmpv4_reply_repr.buffer_len(),
|
||||||
|
ttl: 64,
|
||||||
};
|
};
|
||||||
Ok(Packet::Icmpv4(ipv4_reply_repr, icmpv4_reply_repr))
|
Ok(Packet::Icmpv4(ipv4_reply_repr, icmpv4_reply_repr))
|
||||||
},
|
},
|
||||||
|
@ -270,7 +270,8 @@ mod test {
|
|||||||
src_addr: Ipv4Address([10, 0, 0, 1]),
|
src_addr: Ipv4Address([10, 0, 0, 1]),
|
||||||
dst_addr: Ipv4Address([10, 0, 0, 2]),
|
dst_addr: Ipv4Address([10, 0, 0, 2]),
|
||||||
protocol: IpProtocol::Unknown(IP_PROTO),
|
protocol: IpProtocol::Unknown(IP_PROTO),
|
||||||
payload_len: 4
|
payload_len: 4,
|
||||||
|
ttl: 64
|
||||||
});
|
});
|
||||||
const PACKET_BYTES: [u8; 24] = [
|
const PACKET_BYTES: [u8; 24] = [
|
||||||
0x45, 0x00, 0x00, 0x18,
|
0x45, 0x00, 0x00, 0x18,
|
||||||
|
@ -179,6 +179,8 @@ pub struct TcpSocket<'a> {
|
|||||||
timeout: Option<u64>,
|
timeout: Option<u64>,
|
||||||
/// Interval at which keep-alive packets will be sent.
|
/// Interval at which keep-alive packets will be sent.
|
||||||
keep_alive: Option<u64>,
|
keep_alive: Option<u64>,
|
||||||
|
/// The time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
|
||||||
|
ttl: Option<u8>,
|
||||||
/// Address passed to listen(). Listen address is set when listen() is called and
|
/// Address passed to listen(). Listen address is set when listen() is called and
|
||||||
/// used every time the socket is reset back to the LISTEN state.
|
/// used every time the socket is reset back to the LISTEN state.
|
||||||
listen_address: IpAddress,
|
listen_address: IpAddress,
|
||||||
@ -236,6 +238,7 @@ impl<'a> TcpSocket<'a> {
|
|||||||
rx_buffer: rx_buffer,
|
rx_buffer: rx_buffer,
|
||||||
timeout: None,
|
timeout: None,
|
||||||
keep_alive: None,
|
keep_alive: None,
|
||||||
|
ttl: None,
|
||||||
listen_address: IpAddress::default(),
|
listen_address: IpAddress::default(),
|
||||||
local_endpoint: IpEndpoint::default(),
|
local_endpoint: IpEndpoint::default(),
|
||||||
remote_endpoint: IpEndpoint::default(),
|
remote_endpoint: IpEndpoint::default(),
|
||||||
@ -311,6 +314,33 @@ impl<'a> TcpSocket<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
|
||||||
|
///
|
||||||
|
/// See also the [set_ttl](#method.set_ttl) method
|
||||||
|
pub fn ttl(&self) -> Option<u8> {
|
||||||
|
self.ttl
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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`).
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the local endpoint.
|
/// Return the local endpoint.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn local_endpoint(&self) -> IpEndpoint {
|
pub fn local_endpoint(&self) -> IpEndpoint {
|
||||||
@ -337,6 +367,7 @@ impl<'a> TcpSocket<'a> {
|
|||||||
self.rx_buffer.clear();
|
self.rx_buffer.clear();
|
||||||
self.keep_alive = None;
|
self.keep_alive = None;
|
||||||
self.timeout = None;
|
self.timeout = None;
|
||||||
|
self.ttl = None;
|
||||||
self.listen_address = IpAddress::default();
|
self.listen_address = IpAddress::default();
|
||||||
self.local_endpoint = IpEndpoint::default();
|
self.local_endpoint = IpEndpoint::default();
|
||||||
self.remote_endpoint = IpEndpoint::default();
|
self.remote_endpoint = IpEndpoint::default();
|
||||||
@ -733,7 +764,8 @@ impl<'a> TcpSocket<'a> {
|
|||||||
src_addr: ip_repr.dst_addr(),
|
src_addr: ip_repr.dst_addr(),
|
||||||
dst_addr: ip_repr.src_addr(),
|
dst_addr: ip_repr.src_addr(),
|
||||||
protocol: IpProtocol::Tcp,
|
protocol: IpProtocol::Tcp,
|
||||||
payload_len: reply_repr.buffer_len()
|
payload_len: reply_repr.buffer_len(),
|
||||||
|
ttl: 64
|
||||||
};
|
};
|
||||||
(ip_reply_repr, reply_repr)
|
(ip_reply_repr, reply_repr)
|
||||||
}
|
}
|
||||||
@ -1239,6 +1271,7 @@ impl<'a> TcpSocket<'a> {
|
|||||||
src_addr: self.local_endpoint.addr,
|
src_addr: self.local_endpoint.addr,
|
||||||
dst_addr: self.remote_endpoint.addr,
|
dst_addr: self.remote_endpoint.addr,
|
||||||
protocol: IpProtocol::Tcp,
|
protocol: IpProtocol::Tcp,
|
||||||
|
ttl: self.ttl.unwrap_or(64),
|
||||||
payload_len: 0
|
payload_len: 0
|
||||||
}.lower(&[])?;
|
}.lower(&[])?;
|
||||||
|
|
||||||
@ -1447,7 +1480,8 @@ impl<'a> fmt::Write for TcpSocket<'a> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use wire::{IpAddress, Ipv4Address, IpCidr};
|
use wire::{IpAddress, IpRepr};
|
||||||
|
use wire::{Ipv4Address, IpCidr, Ipv4Repr};
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1479,7 +1513,8 @@ mod test {
|
|||||||
|
|
||||||
const SEND_IP_TEMPL: IpRepr = IpRepr::Unspecified {
|
const SEND_IP_TEMPL: IpRepr = IpRepr::Unspecified {
|
||||||
src_addr: LOCAL_IP, dst_addr: REMOTE_IP,
|
src_addr: LOCAL_IP, dst_addr: REMOTE_IP,
|
||||||
protocol: IpProtocol::Tcp, payload_len: 20
|
protocol: IpProtocol::Tcp, payload_len: 20,
|
||||||
|
ttl: 64
|
||||||
};
|
};
|
||||||
const SEND_TEMPL: TcpRepr<'static> = TcpRepr {
|
const SEND_TEMPL: TcpRepr<'static> = TcpRepr {
|
||||||
src_port: REMOTE_PORT, dst_port: LOCAL_PORT,
|
src_port: REMOTE_PORT, dst_port: LOCAL_PORT,
|
||||||
@ -1490,7 +1525,8 @@ mod test {
|
|||||||
};
|
};
|
||||||
const _RECV_IP_TEMPL: IpRepr = IpRepr::Unspecified {
|
const _RECV_IP_TEMPL: IpRepr = IpRepr::Unspecified {
|
||||||
src_addr: REMOTE_IP, dst_addr: LOCAL_IP,
|
src_addr: REMOTE_IP, dst_addr: LOCAL_IP,
|
||||||
protocol: IpProtocol::Tcp, payload_len: 20
|
protocol: IpProtocol::Tcp, payload_len: 20,
|
||||||
|
ttl: 64
|
||||||
};
|
};
|
||||||
const RECV_TEMPL: TcpRepr<'static> = TcpRepr {
|
const RECV_TEMPL: TcpRepr<'static> = TcpRepr {
|
||||||
src_port: LOCAL_PORT, dst_port: REMOTE_PORT,
|
src_port: LOCAL_PORT, dst_port: REMOTE_PORT,
|
||||||
@ -1506,7 +1542,8 @@ mod test {
|
|||||||
src_addr: REMOTE_IP,
|
src_addr: REMOTE_IP,
|
||||||
dst_addr: LOCAL_IP,
|
dst_addr: LOCAL_IP,
|
||||||
protocol: IpProtocol::Tcp,
|
protocol: IpProtocol::Tcp,
|
||||||
payload_len: repr.buffer_len()
|
payload_len: repr.buffer_len(),
|
||||||
|
ttl: 64
|
||||||
};
|
};
|
||||||
trace!("send: {}", repr);
|
trace!("send: {}", repr);
|
||||||
|
|
||||||
@ -3470,7 +3507,8 @@ mod test {
|
|||||||
src_addr: REMOTE_IP,
|
src_addr: REMOTE_IP,
|
||||||
dst_addr: LOCAL_IP,
|
dst_addr: LOCAL_IP,
|
||||||
protocol: IpProtocol::Tcp,
|
protocol: IpProtocol::Tcp,
|
||||||
payload_len: tcp_repr.buffer_len()
|
payload_len: tcp_repr.buffer_len(),
|
||||||
|
ttl: 64
|
||||||
};
|
};
|
||||||
assert!(s.accepts(&ip_repr, &tcp_repr));
|
assert!(s.accepts(&ip_repr, &tcp_repr));
|
||||||
|
|
||||||
@ -3478,7 +3516,8 @@ mod test {
|
|||||||
src_addr: OTHER_IP,
|
src_addr: OTHER_IP,
|
||||||
dst_addr: LOCAL_IP,
|
dst_addr: LOCAL_IP,
|
||||||
protocol: IpProtocol::Tcp,
|
protocol: IpProtocol::Tcp,
|
||||||
payload_len: tcp_repr.buffer_len()
|
payload_len: tcp_repr.buffer_len(),
|
||||||
|
ttl: 64
|
||||||
};
|
};
|
||||||
assert!(!s.accepts(&ip_repr_wrong_src, &tcp_repr));
|
assert!(!s.accepts(&ip_repr_wrong_src, &tcp_repr));
|
||||||
|
|
||||||
@ -3486,8 +3525,28 @@ mod test {
|
|||||||
src_addr: REMOTE_IP,
|
src_addr: REMOTE_IP,
|
||||||
dst_addr: OTHER_IP,
|
dst_addr: OTHER_IP,
|
||||||
protocol: IpProtocol::Tcp,
|
protocol: IpProtocol::Tcp,
|
||||||
payload_len: tcp_repr.buffer_len()
|
payload_len: tcp_repr.buffer_len(),
|
||||||
|
ttl: 64
|
||||||
};
|
};
|
||||||
assert!(!s.accepts(&ip_repr_wrong_dst, &tcp_repr));
|
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(()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,8 @@ pub struct UdpSocket<'a, 'b: 'a> {
|
|||||||
endpoint: IpEndpoint,
|
endpoint: IpEndpoint,
|
||||||
rx_buffer: SocketBuffer<'a, 'b>,
|
rx_buffer: SocketBuffer<'a, 'b>,
|
||||||
tx_buffer: SocketBuffer<'a, 'b>,
|
tx_buffer: SocketBuffer<'a, 'b>,
|
||||||
|
/// The time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
|
||||||
|
ttl: Option<u8>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> UdpSocket<'a, 'b> {
|
impl<'a, 'b> UdpSocket<'a, 'b> {
|
||||||
@ -74,6 +76,7 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
|
|||||||
endpoint: IpEndpoint::default(),
|
endpoint: IpEndpoint::default(),
|
||||||
rx_buffer: rx_buffer,
|
rx_buffer: rx_buffer,
|
||||||
tx_buffer: tx_buffer,
|
tx_buffer: tx_buffer,
|
||||||
|
ttl: None
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +97,33 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
|
|||||||
self.endpoint
|
self.endpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
|
||||||
|
///
|
||||||
|
/// See also the [set_ttl](#method.set_ttl) method
|
||||||
|
pub fn ttl(&self) -> Option<u8> {
|
||||||
|
self.ttl
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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`).
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Bind the socket to the given endpoint.
|
/// Bind the socket to the given endpoint.
|
||||||
///
|
///
|
||||||
/// This function returns `Err(Error::Illegal)` if the socket was open
|
/// This function returns `Err(Error::Illegal)` if the socket was open
|
||||||
@ -200,6 +230,7 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
|
|||||||
where F: FnOnce((IpRepr, UdpRepr)) -> Result<()> {
|
where F: FnOnce((IpRepr, UdpRepr)) -> Result<()> {
|
||||||
let handle = self.handle;
|
let handle = self.handle;
|
||||||
let endpoint = self.endpoint;
|
let endpoint = self.endpoint;
|
||||||
|
let ttl = self.ttl.unwrap_or(64);
|
||||||
self.tx_buffer.dequeue_one_with(|packet_buf| {
|
self.tx_buffer.dequeue_one_with(|packet_buf| {
|
||||||
net_trace!("{}:{}:{}: sending {} octets",
|
net_trace!("{}:{}:{}: sending {} octets",
|
||||||
handle, endpoint,
|
handle, endpoint,
|
||||||
@ -214,7 +245,8 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
|
|||||||
src_addr: endpoint.addr,
|
src_addr: endpoint.addr,
|
||||||
dst_addr: packet_buf.endpoint.addr,
|
dst_addr: packet_buf.endpoint.addr,
|
||||||
protocol: IpProtocol::Udp,
|
protocol: IpProtocol::Udp,
|
||||||
payload_len: repr.buffer_len()
|
payload_len: repr.buffer_len(),
|
||||||
|
ttl: ttl,
|
||||||
};
|
};
|
||||||
emit((ip_repr, repr))
|
emit((ip_repr, repr))
|
||||||
})
|
})
|
||||||
@ -275,7 +307,8 @@ mod test {
|
|||||||
src_addr: LOCAL_IP,
|
src_addr: LOCAL_IP,
|
||||||
dst_addr: REMOTE_IP,
|
dst_addr: REMOTE_IP,
|
||||||
protocol: IpProtocol::Udp,
|
protocol: IpProtocol::Udp,
|
||||||
payload_len: 8 + 6
|
payload_len: 8 + 6,
|
||||||
|
ttl: 64,
|
||||||
};
|
};
|
||||||
const LOCAL_UDP_REPR: UdpRepr = UdpRepr {
|
const LOCAL_UDP_REPR: UdpRepr = UdpRepr {
|
||||||
src_port: LOCAL_PORT,
|
src_port: LOCAL_PORT,
|
||||||
@ -337,7 +370,8 @@ mod test {
|
|||||||
src_addr: Ipv4Address([10, 0, 0, 2]),
|
src_addr: Ipv4Address([10, 0, 0, 2]),
|
||||||
dst_addr: Ipv4Address([10, 0, 0, 1]),
|
dst_addr: Ipv4Address([10, 0, 0, 1]),
|
||||||
protocol: IpProtocol::Udp,
|
protocol: IpProtocol::Udp,
|
||||||
payload_len: 8 + 6
|
payload_len: 8 + 6,
|
||||||
|
ttl: 64
|
||||||
});
|
});
|
||||||
const REMOTE_UDP_REPR: UdpRepr = UdpRepr {
|
const REMOTE_UDP_REPR: UdpRepr = UdpRepr {
|
||||||
src_port: REMOTE_PORT,
|
src_port: REMOTE_PORT,
|
||||||
@ -407,7 +441,8 @@ mod test {
|
|||||||
src_addr: Ipv4Address([10, 0, 0, 2]),
|
src_addr: Ipv4Address([10, 0, 0, 2]),
|
||||||
dst_addr: Ipv4Address([10, 0, 0, 10]),
|
dst_addr: Ipv4Address([10, 0, 0, 10]),
|
||||||
protocol: IpProtocol::Udp,
|
protocol: IpProtocol::Udp,
|
||||||
payload_len: 8 + 6
|
payload_len: 8 + 6,
|
||||||
|
ttl: 64
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut port_bound_socket = socket(buffer(1), buffer(0));
|
let mut port_bound_socket = socket(buffer(1), buffer(0));
|
||||||
@ -418,4 +453,23 @@ mod test {
|
|||||||
assert_eq!(ip_bound_socket.bind(LOCAL_END), Ok(()));
|
assert_eq!(ip_bound_socket.bind(LOCAL_END), Ok(()));
|
||||||
assert!(!ip_bound_socket.accepts(&ip_repr, &REMOTE_UDP_REPR));
|
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(()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -423,6 +423,7 @@ impl<'a> Repr<'a> {
|
|||||||
dst_addr: ip_packet.dst_addr(),
|
dst_addr: ip_packet.dst_addr(),
|
||||||
protocol: ip_packet.protocol(),
|
protocol: ip_packet.protocol(),
|
||||||
payload_len: payload.len(),
|
payload_len: payload.len(),
|
||||||
|
ttl: ip_packet.ttl()
|
||||||
},
|
},
|
||||||
data: payload
|
data: payload
|
||||||
})
|
})
|
||||||
|
@ -266,7 +266,8 @@ pub enum IpRepr {
|
|||||||
src_addr: Address,
|
src_addr: Address,
|
||||||
dst_addr: Address,
|
dst_addr: Address,
|
||||||
protocol: Protocol,
|
protocol: Protocol,
|
||||||
payload_len: usize
|
payload_len: usize,
|
||||||
|
ttl: u8
|
||||||
},
|
},
|
||||||
Ipv4(Ipv4Repr),
|
Ipv4(Ipv4Repr),
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -336,6 +337,15 @@ impl IpRepr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the TTL value.
|
||||||
|
pub fn ttl(&self) -> u8 {
|
||||||
|
match self {
|
||||||
|
&IpRepr::Unspecified { ttl, .. } => ttl,
|
||||||
|
&IpRepr::Ipv4(Ipv4Repr { ttl, .. }) => ttl,
|
||||||
|
&IpRepr::__Nonexhaustive => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert an unspecified representation into a concrete one, or return
|
/// Convert an unspecified representation into a concrete one, or return
|
||||||
/// `Err(Error::Unaddressable)` if not possible.
|
/// `Err(Error::Unaddressable)` if not possible.
|
||||||
///
|
///
|
||||||
@ -347,20 +357,20 @@ impl IpRepr {
|
|||||||
&IpRepr::Unspecified {
|
&IpRepr::Unspecified {
|
||||||
src_addr: Address::Ipv4(src_addr),
|
src_addr: Address::Ipv4(src_addr),
|
||||||
dst_addr: Address::Ipv4(dst_addr),
|
dst_addr: Address::Ipv4(dst_addr),
|
||||||
protocol, payload_len
|
protocol, payload_len, ttl
|
||||||
} => {
|
} => {
|
||||||
Ok(IpRepr::Ipv4(Ipv4Repr {
|
Ok(IpRepr::Ipv4(Ipv4Repr {
|
||||||
src_addr: src_addr,
|
src_addr: src_addr,
|
||||||
dst_addr: dst_addr,
|
dst_addr: dst_addr,
|
||||||
protocol: protocol,
|
protocol: protocol,
|
||||||
payload_len: payload_len
|
payload_len: payload_len, ttl
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
&IpRepr::Unspecified {
|
&IpRepr::Unspecified {
|
||||||
src_addr: Address::Unspecified,
|
src_addr: Address::Unspecified,
|
||||||
dst_addr: Address::Ipv4(dst_addr),
|
dst_addr: Address::Ipv4(dst_addr),
|
||||||
protocol, payload_len
|
protocol, payload_len, ttl
|
||||||
} => {
|
} => {
|
||||||
let mut src_addr = None;
|
let mut src_addr = None;
|
||||||
for cidr in fallback_src_addrs {
|
for cidr in fallback_src_addrs {
|
||||||
@ -374,9 +384,7 @@ impl IpRepr {
|
|||||||
}
|
}
|
||||||
Ok(IpRepr::Ipv4(Ipv4Repr {
|
Ok(IpRepr::Ipv4(Ipv4Repr {
|
||||||
src_addr: src_addr.ok_or(Error::Unaddressable)?,
|
src_addr: src_addr.ok_or(Error::Unaddressable)?,
|
||||||
dst_addr: dst_addr,
|
dst_addr, protocol, payload_len, ttl
|
||||||
protocol: protocol,
|
|
||||||
payload_len: payload_len
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,12 +542,14 @@ mod test {
|
|||||||
src_addr: IpAddress::Ipv4(ip_addr_a),
|
src_addr: IpAddress::Ipv4(ip_addr_a),
|
||||||
dst_addr: IpAddress::Ipv4(ip_addr_b),
|
dst_addr: IpAddress::Ipv4(ip_addr_b),
|
||||||
protocol: proto,
|
protocol: proto,
|
||||||
payload_len
|
ttl: 0x2a,
|
||||||
|
payload_len,
|
||||||
}.lower(&[]),
|
}.lower(&[]),
|
||||||
Ok(IpRepr::Ipv4(Ipv4Repr{
|
Ok(IpRepr::Ipv4(Ipv4Repr{
|
||||||
src_addr: ip_addr_a,
|
src_addr: ip_addr_a,
|
||||||
dst_addr: ip_addr_b,
|
dst_addr: ip_addr_b,
|
||||||
protocol: proto,
|
protocol: proto,
|
||||||
|
ttl: 0x2a,
|
||||||
payload_len
|
payload_len
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
@ -549,6 +559,7 @@ mod test {
|
|||||||
src_addr: IpAddress::Unspecified,
|
src_addr: IpAddress::Unspecified,
|
||||||
dst_addr: IpAddress::Ipv4(ip_addr_b),
|
dst_addr: IpAddress::Ipv4(ip_addr_b),
|
||||||
protocol: proto,
|
protocol: proto,
|
||||||
|
ttl: 64,
|
||||||
payload_len
|
payload_len
|
||||||
}.lower(&[]),
|
}.lower(&[]),
|
||||||
Err(Error::Unaddressable)
|
Err(Error::Unaddressable)
|
||||||
@ -559,12 +570,14 @@ mod test {
|
|||||||
src_addr: IpAddress::Unspecified,
|
src_addr: IpAddress::Unspecified,
|
||||||
dst_addr: IpAddress::Ipv4(ip_addr_b),
|
dst_addr: IpAddress::Ipv4(ip_addr_b),
|
||||||
protocol: proto,
|
protocol: proto,
|
||||||
|
ttl: 64,
|
||||||
payload_len
|
payload_len
|
||||||
}.lower(&[IpCidr::new(IpAddress::Ipv4(ip_addr_a), 24)]),
|
}.lower(&[IpCidr::new(IpAddress::Ipv4(ip_addr_a), 24)]),
|
||||||
Ok(IpRepr::Ipv4(Ipv4Repr{
|
Ok(IpRepr::Ipv4(Ipv4Repr{
|
||||||
src_addr: ip_addr_a,
|
src_addr: ip_addr_a,
|
||||||
dst_addr: ip_addr_b,
|
dst_addr: ip_addr_b,
|
||||||
protocol: proto,
|
protocol: proto,
|
||||||
|
ttl: 64,
|
||||||
payload_len
|
payload_len
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
@ -574,12 +587,14 @@ mod test {
|
|||||||
src_addr: ip_addr_a,
|
src_addr: ip_addr_a,
|
||||||
dst_addr: ip_addr_b,
|
dst_addr: ip_addr_b,
|
||||||
protocol: proto,
|
protocol: proto,
|
||||||
|
ttl: 255,
|
||||||
payload_len
|
payload_len
|
||||||
}).lower(&[]),
|
}).lower(&[]),
|
||||||
Ok(IpRepr::Ipv4(Ipv4Repr{
|
Ok(IpRepr::Ipv4(Ipv4Repr{
|
||||||
src_addr: ip_addr_a,
|
src_addr: ip_addr_a,
|
||||||
dst_addr: ip_addr_b,
|
dst_addr: ip_addr_b,
|
||||||
protocol: proto,
|
protocol: proto,
|
||||||
|
ttl: 255,
|
||||||
payload_len
|
payload_len
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
@ -589,6 +604,7 @@ mod test {
|
|||||||
src_addr: Ipv4Address::UNSPECIFIED,
|
src_addr: Ipv4Address::UNSPECIFIED,
|
||||||
dst_addr: ip_addr_b,
|
dst_addr: ip_addr_b,
|
||||||
protocol: proto,
|
protocol: proto,
|
||||||
|
ttl: 255,
|
||||||
payload_len
|
payload_len
|
||||||
}).lower(&[]),
|
}).lower(&[]),
|
||||||
Err(Error::Unaddressable)
|
Err(Error::Unaddressable)
|
||||||
@ -599,12 +615,14 @@ mod test {
|
|||||||
src_addr: Ipv4Address::UNSPECIFIED,
|
src_addr: Ipv4Address::UNSPECIFIED,
|
||||||
dst_addr: ip_addr_b,
|
dst_addr: ip_addr_b,
|
||||||
protocol: proto,
|
protocol: proto,
|
||||||
|
ttl: 64,
|
||||||
payload_len
|
payload_len
|
||||||
}).lower(&[IpCidr::new(IpAddress::Ipv4(ip_addr_a), 24)]),
|
}).lower(&[IpCidr::new(IpAddress::Ipv4(ip_addr_a), 24)]),
|
||||||
Ok(IpRepr::Ipv4(Ipv4Repr{
|
Ok(IpRepr::Ipv4(Ipv4Repr{
|
||||||
src_addr: ip_addr_a,
|
src_addr: ip_addr_a,
|
||||||
dst_addr: ip_addr_b,
|
dst_addr: ip_addr_b,
|
||||||
protocol: proto,
|
protocol: proto,
|
||||||
|
ttl: 64,
|
||||||
payload_len
|
payload_len
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
@ -448,7 +448,8 @@ pub struct Repr {
|
|||||||
pub src_addr: Address,
|
pub src_addr: Address,
|
||||||
pub dst_addr: Address,
|
pub dst_addr: Address,
|
||||||
pub protocol: Protocol,
|
pub protocol: Protocol,
|
||||||
pub payload_len: usize
|
pub payload_len: usize,
|
||||||
|
pub ttl: u8
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Repr {
|
impl Repr {
|
||||||
@ -474,7 +475,8 @@ impl Repr {
|
|||||||
src_addr: packet.src_addr(),
|
src_addr: packet.src_addr(),
|
||||||
dst_addr: packet.dst_addr(),
|
dst_addr: packet.dst_addr(),
|
||||||
protocol: packet.protocol(),
|
protocol: packet.protocol(),
|
||||||
payload_len: payload_len
|
payload_len: payload_len,
|
||||||
|
ttl: packet.ttl()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -497,7 +499,7 @@ impl Repr {
|
|||||||
packet.set_more_frags(false);
|
packet.set_more_frags(false);
|
||||||
packet.set_dont_frag(true);
|
packet.set_dont_frag(true);
|
||||||
packet.set_frag_offset(0);
|
packet.set_frag_offset(0);
|
||||||
packet.set_ttl(64);
|
packet.set_ttl(self.ttl);
|
||||||
packet.set_protocol(self.protocol);
|
packet.set_protocol(self.protocol);
|
||||||
packet.set_src_addr(self.src_addr);
|
packet.set_src_addr(self.src_addr);
|
||||||
packet.set_dst_addr(self.dst_addr);
|
packet.set_dst_addr(self.dst_addr);
|
||||||
@ -722,7 +724,8 @@ mod test {
|
|||||||
src_addr: Address([0x11, 0x12, 0x13, 0x14]),
|
src_addr: Address([0x11, 0x12, 0x13, 0x14]),
|
||||||
dst_addr: Address([0x21, 0x22, 0x23, 0x24]),
|
dst_addr: Address([0x21, 0x22, 0x23, 0x24]),
|
||||||
protocol: Protocol::Icmp,
|
protocol: Protocol::Icmp,
|
||||||
payload_len: 4
|
payload_len: 4,
|
||||||
|
ttl: 64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -733,6 +736,17 @@ mod test {
|
|||||||
assert_eq!(repr, packet_repr());
|
assert_eq!(repr, packet_repr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_bad_version() {
|
||||||
|
let mut bytes = vec![0; 24];
|
||||||
|
bytes.copy_from_slice(&REPR_PACKET_BYTES[..]);
|
||||||
|
let mut packet = Packet::new(&mut bytes);
|
||||||
|
packet.set_version(6);
|
||||||
|
packet.fill_checksum();
|
||||||
|
let packet = Packet::new(&*packet.into_inner());
|
||||||
|
assert_eq!(Repr::parse(&packet, &ChecksumCapabilities::default()), Err(Error::Malformed));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_total_len_underflow() {
|
fn test_parse_total_len_underflow() {
|
||||||
let mut bytes = vec![0; 24];
|
let mut bytes = vec![0; 24];
|
||||||
|
@ -52,7 +52,8 @@ let repr = Ipv4Repr {
|
|||||||
src_addr: Ipv4Address::new(10, 0, 0, 1),
|
src_addr: Ipv4Address::new(10, 0, 0, 1),
|
||||||
dst_addr: Ipv4Address::new(10, 0, 0, 2),
|
dst_addr: Ipv4Address::new(10, 0, 0, 2),
|
||||||
protocol: IpProtocol::Tcp,
|
protocol: IpProtocol::Tcp,
|
||||||
payload_len: 10
|
payload_len: 10,
|
||||||
|
ttl: 64
|
||||||
};
|
};
|
||||||
let mut buffer = vec![0; repr.buffer_len() + repr.payload_len];
|
let mut buffer = vec![0; repr.buffer_len() + repr.payload_len];
|
||||||
{ // emission
|
{ // emission
|
||||||
|
Loading…
x
Reference in New Issue
Block a user