Skip to content

Commit

Permalink
Add support for IPV6_TCLASS and IPV6_RECVTCLASS
Browse files Browse the repository at this point in the history
A simple implementation of the IPV6_TCLASS and IPV6_RECVTCLASS modeled
after the existing IP_TOS and IP_RECVTOS implementations.

Remove useless bool to i32 conversion in `set_recv_tos`

close #363
  • Loading branch information
duskmoon314 authored and Thomasdezeeuw committed Dec 21, 2022
1 parent 05ca989 commit bada246
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 8 deletions.
48 changes: 46 additions & 2 deletions src/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1445,8 +1445,6 @@ impl Socket {
target_os = "solaris",
)))]
pub fn set_recv_tos(&self, recv_tos: bool) -> io::Result<()> {
let recv_tos = i32::from(recv_tos);

unsafe {
setsockopt(
self.as_raw(),
Expand Down Expand Up @@ -1668,6 +1666,52 @@ impl Socket {
)
}
}

/// Get the value of the `IPV6_RECVTCLASS` option for this socket.
///
/// For more information about this option, see [`set_recv_tclass_v6`].
///
/// [`set_recv_tclass_v6`]: Socket::set_recv_tclass_v6
#[cfg(not(any(
target_os = "dragonfly",
target_os = "fuchsia",
target_os = "illumos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "solaris",
)))]
pub fn recv_tclass_v6(&self) -> io::Result<bool> {
unsafe {
getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_RECVTCLASS)
.map(|recv_tclass| recv_tclass > 0)
}
}

/// Set the value of the `IPV6_RECVTCLASS` option for this socket.
///
/// If enabled, the `IPV6_TCLASS` ancillary message is passed with incoming
/// packets. It contains a byte which specifies the traffic class field of
/// the packet header.
#[cfg(not(any(
target_os = "dragonfly",
target_os = "fuchsia",
target_os = "illumos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "solaris",
)))]
pub fn set_recv_tclass_v6(&self, recv_tclass: bool) -> io::Result<()> {
unsafe {
setsockopt(
self.as_raw(),
sys::IPPROTO_IPV6,
sys::IPV6_RECVTCLASS,
recv_tclass as c_int,
)
}
}
}

/// Socket options for TCP sockets, get/set using `IPPROTO_TCP`.
Expand Down
95 changes: 95 additions & 0 deletions src/sys/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ pub(crate) use libc::{
#[cfg(not(target_os = "redox"))]
pub(crate) use libc::{MSG_TRUNC, SO_OOBINLINE};
// Used in `Socket`.
#[cfg(not(any(
target_os = "dragonfly",
target_os = "fuchsia",
target_os = "illumos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "solaris",
)))]
pub(crate) use libc::IPV6_RECVTCLASS;
#[cfg(all(feature = "all", not(target_os = "redox")))]
pub(crate) use libc::IP_HDRINCL;
#[cfg(not(any(
Expand Down Expand Up @@ -2057,6 +2067,91 @@ impl crate::Socket {
pub fn detach_filter(&self) -> io::Result<()> {
unsafe { setsockopt(self.as_raw(), libc::SOL_SOCKET, libc::SO_DETACH_FILTER, 0) }
}

/// Get the value of the `IPV6_TCLASS` option for this socket.
///
/// For more information about this option, see [`set_tclass_v6`].
///
/// [`set_tclass_v6`]: Socket::set_tclass_v6
#[cfg(all(
feature = "all",
any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
)
))]
#[cfg_attr(
docsrs,
doc(cfg(all(
feature = "all",
any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
)
)))
)]
pub fn tclass_v6(&self) -> io::Result<u32> {
unsafe {
getsockopt::<c_int>(self.as_raw(), IPPROTO_IPV6, libc::IPV6_TCLASS)
.map(|tclass| tclass as u32)
}
}

/// Set the value of the `IPV6_TCLASS` option for this socket.
///
/// Specifies the traffic class field that is used in every packets
/// sent from this socket.
#[cfg(all(
feature = "all",
any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
)
))]
#[cfg_attr(
docsrs,
doc(cfg(all(
feature = "all",
any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
)
)))
)]
pub fn set_tclass_v6(&self, tclass: u32) -> io::Result<()> {
unsafe {
setsockopt(
self.as_raw(),
IPPROTO_IPV6,
libc::IPV6_TCLASS,
tclass as c_int,
)
}
}
}

#[cfg_attr(docsrs, doc(cfg(unix)))]
Expand Down
13 changes: 7 additions & 6 deletions src/sys/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,13 @@ pub(crate) type socklen_t = i32;
pub(crate) use windows_sys::Win32::Networking::WinSock::IP_HDRINCL;
pub(crate) use windows_sys::Win32::Networking::WinSock::{
linger, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MREQ as Ipv6Mreq,
IPV6_MULTICAST_HOPS, IPV6_MULTICAST_IF, IPV6_MULTICAST_LOOP, IPV6_UNICAST_HOPS, IPV6_V6ONLY,
IP_ADD_MEMBERSHIP, IP_ADD_SOURCE_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_DROP_SOURCE_MEMBERSHIP,
IP_MREQ as IpMreq, IP_MREQ_SOURCE as IpMreqSource, IP_MULTICAST_IF, IP_MULTICAST_LOOP,
IP_MULTICAST_TTL, IP_RECVTOS, IP_TOS, IP_TTL, MSG_OOB, MSG_PEEK, SO_BROADCAST, SO_ERROR,
SO_KEEPALIVE, SO_LINGER, SO_OOBINLINE, SO_RCVBUF, SO_RCVTIMEO, SO_REUSEADDR, SO_SNDBUF,
SO_SNDTIMEO, SO_TYPE, TCP_NODELAY,
IPV6_MULTICAST_HOPS, IPV6_MULTICAST_IF, IPV6_MULTICAST_LOOP, IPV6_RECVTCLASS,
IPV6_UNICAST_HOPS, IPV6_V6ONLY, IP_ADD_MEMBERSHIP, IP_ADD_SOURCE_MEMBERSHIP,
IP_DROP_MEMBERSHIP, IP_DROP_SOURCE_MEMBERSHIP, IP_MREQ as IpMreq,
IP_MREQ_SOURCE as IpMreqSource, IP_MULTICAST_IF, IP_MULTICAST_LOOP, IP_MULTICAST_TTL,
IP_RECVTOS, IP_TOS, IP_TTL, MSG_OOB, MSG_PEEK, SO_BROADCAST, SO_ERROR, SO_KEEPALIVE, SO_LINGER,
SO_OOBINLINE, SO_RCVBUF, SO_RCVTIMEO, SO_REUSEADDR, SO_SNDBUF, SO_SNDTIMEO, SO_TYPE,
TCP_NODELAY,
};
pub(crate) const IPPROTO_IP: c_int = windows_sys::Win32::Networking::WinSock::IPPROTO_IP as c_int;
pub(crate) const SOL_SOCKET: c_int = windows_sys::Win32::Networking::WinSock::SOL_SOCKET as c_int;
Expand Down
27 changes: 27 additions & 0 deletions tests/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,33 @@ test!(IPv6 only_v6, set_only_v6(true));
#[cfg(any(windows, target_os = "freebsd"))]
test!(IPv6 only_v6, set_only_v6(false));

#[cfg(all(
feature = "all",
any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"
)
))]
test!(IPv6 tclass_v6, set_tclass_v6(96));

#[cfg(not(any(
target_os = "dragonfly",
target_os = "fuchsia",
target_os = "illumos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "redox",
target_os = "solaris",
target_os = "windows",
)))]
test!(IPv6 recv_tclass_v6, set_recv_tclass_v6(true));

#[cfg(all(
feature = "all",
any(target_os = "android", target_os = "fuchsia", target_os = "linux")
Expand Down

0 comments on commit bada246

Please sign in to comment.