Skip to content

Commit 43f286c

Browse files
duskmoon314Thomasdezeeuw
authored andcommitted
Add support for IPV6_TCLASS and IPV6_RECVTCLASS
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
1 parent 24973b2 commit 43f286c

File tree

4 files changed

+175
-8
lines changed

4 files changed

+175
-8
lines changed

src/socket.rs

+46-2
Original file line numberDiff line numberDiff line change
@@ -1444,8 +1444,6 @@ impl Socket {
14441444
target_os = "solaris",
14451445
)))]
14461446
pub fn set_recv_tos(&self, recv_tos: bool) -> io::Result<()> {
1447-
let recv_tos = i32::from(recv_tos);
1448-
14491447
unsafe {
14501448
setsockopt(
14511449
self.as_raw(),
@@ -1667,6 +1665,52 @@ impl Socket {
16671665
)
16681666
}
16691667
}
1668+
1669+
/// Get the value of the `IPV6_RECVTCLASS` option for this socket.
1670+
///
1671+
/// For more information about this option, see [`set_recv_tclass_v6`].
1672+
///
1673+
/// [`set_recv_tclass_v6`]: Socket::set_recv_tclass_v6
1674+
#[cfg(not(any(
1675+
target_os = "dragonfly",
1676+
target_os = "fuchsia",
1677+
target_os = "illumos",
1678+
target_os = "netbsd",
1679+
target_os = "openbsd",
1680+
target_os = "redox",
1681+
target_os = "solaris",
1682+
)))]
1683+
pub fn recv_tclass_v6(&self) -> io::Result<bool> {
1684+
unsafe {
1685+
getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IPV6, sys::IPV6_RECVTCLASS)
1686+
.map(|recv_tclass| recv_tclass > 0)
1687+
}
1688+
}
1689+
1690+
/// Set the value of the `IPV6_RECVTCLASS` option for this socket.
1691+
///
1692+
/// If enabled, the `IPV6_TCLASS` ancillary message is passed with incoming
1693+
/// packets. It contains a byte which specifies the traffic class field of
1694+
/// the packet header.
1695+
#[cfg(not(any(
1696+
target_os = "dragonfly",
1697+
target_os = "fuchsia",
1698+
target_os = "illumos",
1699+
target_os = "netbsd",
1700+
target_os = "openbsd",
1701+
target_os = "redox",
1702+
target_os = "solaris",
1703+
)))]
1704+
pub fn set_recv_tclass_v6(&self, recv_tclass: bool) -> io::Result<()> {
1705+
unsafe {
1706+
setsockopt(
1707+
self.as_raw(),
1708+
sys::IPPROTO_IPV6,
1709+
sys::IPV6_RECVTCLASS,
1710+
recv_tclass as c_int,
1711+
)
1712+
}
1713+
}
16701714
}
16711715

16721716
/// Socket options for TCP sockets, get/set using `IPPROTO_TCP`.

src/sys/unix.rs

+95
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ pub(crate) use libc::{
7676
#[cfg(not(target_os = "redox"))]
7777
pub(crate) use libc::{MSG_TRUNC, SO_OOBINLINE};
7878
// Used in `Socket`.
79+
#[cfg(not(any(
80+
target_os = "dragonfly",
81+
target_os = "fuchsia",
82+
target_os = "illumos",
83+
target_os = "netbsd",
84+
target_os = "openbsd",
85+
target_os = "redox",
86+
target_os = "solaris",
87+
)))]
88+
pub(crate) use libc::IPV6_RECVTCLASS;
7989
#[cfg(all(feature = "all", not(target_os = "redox")))]
8090
pub(crate) use libc::IP_HDRINCL;
8191
#[cfg(not(any(
@@ -2057,6 +2067,91 @@ impl crate::Socket {
20572067
pub fn detach_filter(&self) -> io::Result<()> {
20582068
unsafe { setsockopt(self.as_raw(), libc::SOL_SOCKET, libc::SO_DETACH_FILTER, 0) }
20592069
}
2070+
2071+
/// Get the value of the `IPV6_TCLASS` option for this socket.
2072+
///
2073+
/// For more information about this option, see [`set_tclass_v6`].
2074+
///
2075+
/// [`set_tclass_v6`]: Socket::set_tclass_v6
2076+
#[cfg(all(
2077+
feature = "all",
2078+
any(
2079+
target_os = "android",
2080+
target_os = "dragonfly",
2081+
target_os = "freebsd",
2082+
target_os = "fuchsia",
2083+
target_os = "linux",
2084+
target_os = "macos",
2085+
target_os = "netbsd",
2086+
target_os = "openbsd"
2087+
)
2088+
))]
2089+
#[cfg_attr(
2090+
docsrs,
2091+
doc(cfg(all(
2092+
feature = "all",
2093+
any(
2094+
target_os = "android",
2095+
target_os = "dragonfly",
2096+
target_os = "freebsd",
2097+
target_os = "fuchsia",
2098+
target_os = "linux",
2099+
target_os = "macos",
2100+
target_os = "netbsd",
2101+
target_os = "openbsd"
2102+
)
2103+
)))
2104+
)]
2105+
pub fn tclass_v6(&self) -> io::Result<u32> {
2106+
unsafe {
2107+
getsockopt::<c_int>(self.as_raw(), IPPROTO_IPV6, libc::IPV6_TCLASS)
2108+
.map(|tclass| tclass as u32)
2109+
}
2110+
}
2111+
2112+
/// Set the value of the `IPV6_TCLASS` option for this socket.
2113+
///
2114+
/// Specifies the traffic class field that is used in every packets
2115+
/// sent from this socket.
2116+
#[cfg(all(
2117+
feature = "all",
2118+
any(
2119+
target_os = "android",
2120+
target_os = "dragonfly",
2121+
target_os = "freebsd",
2122+
target_os = "fuchsia",
2123+
target_os = "linux",
2124+
target_os = "macos",
2125+
target_os = "netbsd",
2126+
target_os = "openbsd"
2127+
)
2128+
))]
2129+
#[cfg_attr(
2130+
docsrs,
2131+
doc(cfg(all(
2132+
feature = "all",
2133+
any(
2134+
target_os = "android",
2135+
target_os = "dragonfly",
2136+
target_os = "freebsd",
2137+
target_os = "fuchsia",
2138+
target_os = "linux",
2139+
target_os = "macos",
2140+
target_os = "netbsd",
2141+
target_os = "openbsd"
2142+
)
2143+
)))
2144+
)]
2145+
pub fn set_tclass_v6(&self, tclass: u32) -> io::Result<()> {
2146+
unsafe {
2147+
setsockopt(
2148+
self.as_raw(),
2149+
IPPROTO_IPV6,
2150+
libc::IPV6_TCLASS,
2151+
tclass as c_int,
2152+
)
2153+
}
2154+
}
20602155
}
20612156

20622157
#[cfg_attr(docsrs, doc(cfg(unix)))]

src/sys/windows.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,13 @@ pub(crate) type socklen_t = i32;
6969
pub(crate) use windows_sys::Win32::Networking::WinSock::IP_HDRINCL;
7070
pub(crate) use windows_sys::Win32::Networking::WinSock::{
7171
linger, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MREQ as Ipv6Mreq,
72-
IPV6_MULTICAST_HOPS, IPV6_MULTICAST_IF, IPV6_MULTICAST_LOOP, IPV6_UNICAST_HOPS, IPV6_V6ONLY,
73-
IP_ADD_MEMBERSHIP, IP_ADD_SOURCE_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_DROP_SOURCE_MEMBERSHIP,
74-
IP_MREQ as IpMreq, IP_MREQ_SOURCE as IpMreqSource, IP_MULTICAST_IF, IP_MULTICAST_LOOP,
75-
IP_MULTICAST_TTL, IP_RECVTOS, IP_TOS, IP_TTL, MSG_OOB, MSG_PEEK, SO_BROADCAST, SO_ERROR,
76-
SO_KEEPALIVE, SO_LINGER, SO_OOBINLINE, SO_RCVBUF, SO_RCVTIMEO, SO_REUSEADDR, SO_SNDBUF,
77-
SO_SNDTIMEO, SO_TYPE, TCP_NODELAY,
72+
IPV6_MULTICAST_HOPS, IPV6_MULTICAST_IF, IPV6_MULTICAST_LOOP, IPV6_RECVTCLASS,
73+
IPV6_UNICAST_HOPS, IPV6_V6ONLY, IP_ADD_MEMBERSHIP, IP_ADD_SOURCE_MEMBERSHIP,
74+
IP_DROP_MEMBERSHIP, IP_DROP_SOURCE_MEMBERSHIP, IP_MREQ as IpMreq,
75+
IP_MREQ_SOURCE as IpMreqSource, IP_MULTICAST_IF, IP_MULTICAST_LOOP, IP_MULTICAST_TTL,
76+
IP_RECVTOS, IP_TOS, IP_TTL, MSG_OOB, MSG_PEEK, SO_BROADCAST, SO_ERROR, SO_KEEPALIVE, SO_LINGER,
77+
SO_OOBINLINE, SO_RCVBUF, SO_RCVTIMEO, SO_REUSEADDR, SO_SNDBUF, SO_SNDTIMEO, SO_TYPE,
78+
TCP_NODELAY,
7879
};
7980
pub(crate) const IPPROTO_IP: c_int = windows_sys::Win32::Networking::WinSock::IPPROTO_IP as c_int;
8081
pub(crate) const SOL_SOCKET: c_int = windows_sys::Win32::Networking::WinSock::SOL_SOCKET as c_int;

tests/socket.rs

+27
Original file line numberDiff line numberDiff line change
@@ -1199,6 +1199,33 @@ test!(IPv6 only_v6, set_only_v6(true));
11991199
#[cfg(any(windows, target_os = "freebsd"))]
12001200
test!(IPv6 only_v6, set_only_v6(false));
12011201

1202+
#[cfg(all(
1203+
feature = "all",
1204+
any(
1205+
target_os = "android",
1206+
target_os = "dragonfly",
1207+
target_os = "freebsd",
1208+
target_os = "fuchsia",
1209+
target_os = "linux",
1210+
target_os = "macos",
1211+
target_os = "netbsd",
1212+
target_os = "openbsd"
1213+
)
1214+
))]
1215+
test!(IPv6 tclass_v6, set_tclass_v6(96));
1216+
1217+
#[cfg(not(any(
1218+
target_os = "dragonfly",
1219+
target_os = "fuchsia",
1220+
target_os = "illumos",
1221+
target_os = "netbsd",
1222+
target_os = "openbsd",
1223+
target_os = "redox",
1224+
target_os = "solaris",
1225+
target_os = "windows",
1226+
)))]
1227+
test!(IPv6 recv_tclass_v6, set_recv_tclass_v6(true));
1228+
12021229
#[cfg(all(
12031230
feature = "all",
12041231
any(target_os = "android", target_os = "fuchsia", target_os = "linux")

0 commit comments

Comments
 (0)