Skip to content

Commit

Permalink
Fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
sunfishcode committed Sep 29, 2023
1 parent 495a1c7 commit 7d1c57f
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 43 deletions.
26 changes: 18 additions & 8 deletions src/backend/libc/net/sockopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use super::ext::{in6_addr_new, in_addr_new};
use crate::backend::c;
use crate::backend::conv::{borrowed_fd, ret};
use crate::fd::BorrowedFd;
#[cfg(feature = "alloc")]
#[cfg(any(linux_like, solarish, target_os = "freebsd", target_os = "fuchsia"))]
use crate::ffi::CStr;
use crate::io;
Expand All @@ -21,7 +22,7 @@ use crate::net::sockopt::Timeout;
)))]
use crate::net::AddressFamily;
#[cfg(any(
linux_like,
linux_kernel,
target_os = "freebsd",
target_os = "fuchsia",
target_os = "openbsd",
Expand All @@ -30,11 +31,12 @@ use crate::net::AddressFamily;
))]
use crate::net::Protocol;
#[cfg(any(
linux_like,
linux_kernel,
target_os = "freebsd",
target_os = "fuchsia",
target_os = "openbsd",
target_os = "redox"
target_os = "redox",
target_env = "newlib"
))]
use crate::net::RawProtocol;
#[cfg(linux_kernel)]
Expand All @@ -43,6 +45,12 @@ use crate::net::{Ipv4Addr, Ipv6Addr, SocketType};
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
use crate::net::{SocketAddrAny, SocketAddrStorage, SocketAddrV4};
use crate::utils::as_mut_ptr;
#[cfg(feature = "alloc")]
#[cfg(any(linux_like, solarish, target_os = "freebsd", target_os = "fuchsia"))]
use alloc::borrow::ToOwned;
#[cfg(feature = "alloc")]
#[cfg(any(linux_like, solarish, target_os = "freebsd", target_os = "fuchsia"))]
use alloc::string::String;
#[cfg(apple)]
use c::TCP_KEEPALIVE as TCP_KEEPIDLE;
#[cfg(not(any(apple, target_os = "openbsd", target_os = "haiku", target_os = "nto")))]
Expand Down Expand Up @@ -393,7 +401,7 @@ pub(crate) fn get_socket_reuseport_lb(fd: BorrowedFd<'_>) -> io::Result<bool> {
}

#[cfg(any(
linux_like,
linux_kernel,
target_os = "freebsd",
target_os = "fuchsia",
target_os = "openbsd",
Expand All @@ -411,7 +419,7 @@ pub(crate) fn get_socket_protocol(fd: BorrowedFd<'_>) -> io::Result<Option<Proto
})
}

#[cfg(linux_like)]
#[cfg(target_os = "linux")]
#[inline]
pub(crate) fn get_socket_cookie(fd: BorrowedFd<'_>) -> io::Result<u64> {
getsockopt(fd, c::SOL_SOCKET, c::SO_COOKIE)
Expand Down Expand Up @@ -770,13 +778,13 @@ pub(crate) fn get_ipv6_original_dst(fd: BorrowedFd<'_>) -> io::Result<SocketAddr
}
}

#[cfg(not(solarish))]
#[cfg(not(any(solarish, target_os = "espidf", target_os = "haiku")))]
#[inline]
pub(crate) fn set_ipv6_tclass(fd: BorrowedFd<'_>, value: u32) -> io::Result<()> {
setsockopt(fd, c::IPPROTO_IPV6, c::IPV6_TCLASS, value)
}

#[cfg(not(solarish))]
#[cfg(not(any(solarish, target_os = "espidf", target_os = "haiku")))]
#[inline]
pub(crate) fn get_ipv6_tclass(fd: BorrowedFd<'_>) -> io::Result<u32> {
getsockopt(fd, c::IPPROTO_IPV6, c::IPV6_TCLASS)
Expand Down Expand Up @@ -865,6 +873,7 @@ pub(crate) fn set_tcp_congestion(fd: BorrowedFd<'_>, value: &str) -> io::Result<
setsockopt_raw(fd, level, optname, value.as_ptr(), optlen)
}

#[cfg(feature = "alloc")]
#[cfg(any(linux_like, solarish, target_os = "freebsd", target_os = "fuchsia"))]
#[inline]
pub(crate) fn get_tcp_congestion(fd: BorrowedFd<'_>) -> io::Result<String> {
Expand All @@ -877,8 +886,9 @@ pub(crate) fn get_tcp_congestion(fd: BorrowedFd<'_>) -> io::Result<String> {
unsafe {
let value = value.assume_init();
let slice: &[u8] = core::mem::transmute(&value[..optlen as usize]);
assert!(slice.iter().any(|b| *b == b'\0'));
Ok(
core::str::from_utf8(CStr::from_bytes_until_nul(slice).unwrap().to_bytes())
core::str::from_utf8(CStr::from_ptr(slice.as_ptr().cast()).to_bytes())
.unwrap()
.to_owned(),
)
Expand Down
1 change: 1 addition & 0 deletions src/backend/libc/process/types.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[cfg(not(target_os = "espidf"))]
use crate::backend::c;

/// A command for use with [`membarrier`] and [`membarrier_cpu`].
Expand Down
16 changes: 11 additions & 5 deletions src/backend/linux_raw/net/sockopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@
use crate::backend::c;
use crate::backend::conv::{by_mut, c_uint, ret, socklen_t};
use crate::fd::BorrowedFd;
#[cfg(feature = "alloc")]
use crate::ffi::CStr;
use crate::io;
use crate::net::sockopt::Timeout;
use crate::net::{
AddressFamily, Ipv4Addr, Ipv6Addr, Protocol, RawProtocol, SocketAddrAny, SocketAddrStorage,
SocketAddrV4, SocketAddrV6, SocketType,
};
#[cfg(feature = "alloc")]
use alloc::borrow::ToOwned;
#[cfg(feature = "alloc")]
use alloc::string::String;
use core::mem::MaybeUninit;
use core::time::Duration;
use linux_raw_sys::general::{__kernel_old_timeval, __kernel_sock_timeval};
Expand Down Expand Up @@ -66,16 +71,15 @@ fn getsockopt_raw<T>(
}
#[cfg(target_arch = "x86")]
unsafe {
let mut value = MaybeUninit::<T>::uninit();
ret(syscall!(
__NR_socketcall,
x86_sys(SYS_GETSOCKOPT),
slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
fd.into(),
c_uint(level),
c_uint(optname),
(&mut value).into(),
by_mut(&mut optlen),
value.into(),
by_mut(optlen),
])
))
}
Expand Down Expand Up @@ -119,7 +123,7 @@ fn setsockopt_raw<T>(
fd.into(),
c_uint(level),
c_uint(optname),
ptr,
ptr.into(),
socklen_t(optlen),
])
))
Expand Down Expand Up @@ -749,6 +753,7 @@ pub(crate) fn set_tcp_congestion(fd: BorrowedFd<'_>, value: &str) -> io::Result<
setsockopt_raw(fd, level, optname, value.as_ptr(), optlen)
}

#[cfg(feature = "alloc")]
#[inline]
pub(crate) fn get_tcp_congestion(fd: BorrowedFd<'_>) -> io::Result<String> {
let level = c::IPPROTO_TCP;
Expand All @@ -760,8 +765,9 @@ pub(crate) fn get_tcp_congestion(fd: BorrowedFd<'_>) -> io::Result<String> {
unsafe {
let value = value.assume_init();
let slice: &[u8] = core::mem::transmute(&value[..optlen as usize]);
assert!(slice.iter().any(|b| *b == b'\0'));
Ok(
core::str::from_utf8(CStr::from_bytes_until_nul(slice).unwrap().to_bytes())
core::str::from_utf8(CStr::from_ptr(slice.as_ptr().cast()).to_bytes())
.unwrap()
.to_owned(),
)
Expand Down
12 changes: 8 additions & 4 deletions src/net/sockopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ use crate::net::SocketAddrV4;
use crate::net::SocketAddrV6;
use crate::net::{Ipv4Addr, Ipv6Addr, SocketType};
use crate::{backend, io};
#[cfg(feature = "alloc")]
#[cfg(any(linux_like, solarish, target_os = "freebsd", target_os = "fuchsia"))]
use alloc::string::String;
use backend::c;
use backend::fd::AsFd;
use core::time::Duration;
Expand Down Expand Up @@ -529,7 +532,7 @@ pub fn get_socket_reuseport_lb<Fd: AsFd>(fd: Fd) -> io::Result<bool> {
///
/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions
#[cfg(any(
linux_like,
linux_kernel,
target_os = "freebsd",
target_os = "fuchsia",
target_os = "openbsd",
Expand All @@ -547,7 +550,7 @@ pub fn get_socket_protocol<Fd: AsFd>(fd: Fd) -> io::Result<Option<Protocol>> {
/// See the [module-level documentation] for more.
///
/// [module-level documentation]: self#references-for-get_socket_-and-set_socket_-functions
#[cfg(linux_like)]
#[cfg(target_os = "linux")]
#[inline]
#[doc(alias = "SO_COOKIE")]
pub fn get_socket_cookie<Fd: AsFd>(fd: Fd) -> io::Result<u64> {
Expand Down Expand Up @@ -1089,7 +1092,7 @@ pub fn get_ipv6_original_dst<Fd: AsFd>(fd: Fd) -> io::Result<SocketAddrV6> {
/// See the [module-level documentation] for more.
///
/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions
#[cfg(not(solarish))]
#[cfg(not(any(solarish, target_os = "espidf", target_os = "haiku")))]
#[inline]
#[doc(alias = "IPV6_TCLASS")]
pub fn set_ipv6_tclass<Fd: AsFd>(fd: Fd, value: u32) -> io::Result<()> {
Expand All @@ -1101,7 +1104,7 @@ pub fn set_ipv6_tclass<Fd: AsFd>(fd: Fd, value: u32) -> io::Result<()> {
/// See the [module-level documentation] for more.
///
/// [module-level documentation]: self#references-for-get_ipv6_-and-set_ipv6_-functions
#[cfg(not(solarish))]
#[cfg(not(any(solarish, target_os = "espidf", target_os = "haiku")))]
#[inline]
#[doc(alias = "IPV6_TCLASS")]
pub fn get_ipv6_tclass<Fd: AsFd>(fd: Fd) -> io::Result<u32> {
Expand Down Expand Up @@ -1271,6 +1274,7 @@ pub fn set_tcp_congestion<Fd: AsFd>(fd: Fd, value: &str) -> io::Result<()> {
/// See the [module-level documentation] for more.
///
/// [module-level documentation]: self#references-for-get_tcp_-and-set_tcp_-functions
#[cfg(feature = "alloc")]
#[cfg(any(linux_like, solarish, target_os = "freebsd", target_os = "fuchsia"))]
#[inline]
#[doc(alias = "TCP_CONGESTION")]
Expand Down
78 changes: 52 additions & 26 deletions tests/net/sockopt.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
use rustix::fd::OwnedFd;
use rustix::io;
use rustix::net::sockopt;
use rustix::net::{ipproto, AddressFamily, SocketType};
#[cfg(any(
linux_like,
target_os = "freebsd",
target_os = "fuchsia",
target_os = "openbsd",
target_os = "redox",
target_env = "newlib"
))]
use rustix::net::ipproto;
use rustix::net::{sockopt, AddressFamily, SocketType};
use std::time::Duration;

// Test `socket` socket options.
Expand All @@ -11,10 +19,20 @@ fn test_sockopts_socket(s: &OwnedFd) {
.unwrap()
.is_none());
assert_eq!(sockopt::get_socket_type(&s).unwrap(), SocketType::STREAM);
assert_eq!(
sockopt::get_socket_protocol(&s).unwrap(),
Some(ipproto::TCP)
);
#[cfg(any(
linux_kernel,
target_os = "freebsd",
target_os = "fuchsia",
target_os = "openbsd",
target_os = "redox",
target_env = "newlib"
))]
{
assert_eq!(
sockopt::get_socket_protocol(&s).unwrap(),
Some(ipproto::TCP)
);
}
assert!(!sockopt::get_socket_reuseaddr(&s).unwrap());
#[cfg(not(windows))]
assert!(!sockopt::get_socket_broadcast(&s).unwrap());
Expand Down Expand Up @@ -137,17 +155,20 @@ fn test_sockopts_socket(s: &OwnedFd) {
// Check the initial value of SO_REUSEPORT_LB, set it, and check it.
#[cfg(target_os = "freebsd")]
{
assert_eq!(!sockopt::get_socket_reuseport_lb(&s).unwrap());
assert!(!sockopt::get_socket_reuseport_lb(&s).unwrap());
sockopt::set_socket_reuseport_lb(&s, true).unwrap();
assert_eq!(sockopt::get_socket_reuseport_lb(&s).unwrap());
assert!(sockopt::get_socket_reuseport_lb(&s).unwrap());
}

// Not much we can check with `get_socket_cookie`, but make sure we can
// call it and that it returns the same value if called twice.
assert_eq!(
sockopt::get_socket_cookie(&s).unwrap(),
sockopt::get_socket_cookie(&s).unwrap()
);
#[cfg(target_os = "linux")]
{
assert_eq!(
sockopt::get_socket_cookie(&s).unwrap(),
sockopt::get_socket_cookie(&s).unwrap()
);
}

// Check the initial value of SO_INCOMING_CPU, set it, and check it.
#[cfg(target_os = "linux")]
Expand Down Expand Up @@ -211,8 +232,10 @@ fn test_sockopts_tcp(s: &OwnedFd) {

// Check the initial value of TCP_CONGESTION, set it, and check it.
#[cfg(any(linux_like, solarish, target_os = "freebsd", target_os = "fuchsia"))]
#[cfg(feature = "alloc")]
{
assert_eq!(sockopt::get_tcp_congestion(&s).unwrap(), "cubic");
let algo = sockopt::get_tcp_congestion(&s).unwrap();
assert!(!algo.is_empty());
sockopt::set_tcp_congestion(&s, "reno").unwrap();
assert_eq!(sockopt::get_tcp_congestion(&s).unwrap(), "reno");
}
Expand Down Expand Up @@ -313,7 +336,10 @@ fn test_sockopts_ipv4() {
// Check that we can query SO_ORIGINAL_DST.
#[cfg(any(linux_kernel, target_os = "fuchsia"))]
{
assert_eq!(sockopt::get_ip_original_dst(&s), Err(io::Errno::NOPROTOOPT));
assert!(matches!(
sockopt::get_ip_original_dst(&s),
Err(io::Errno::NOENT | io::Errno::NOPROTOOPT)
));
}

test_sockopts_tcp(&s);
Expand Down Expand Up @@ -343,9 +369,9 @@ fn test_sockopts_ipv6() {
assert_ne!(sockopt::get_ipv6_unicast_hops(&s).unwrap(), 0);
match sockopt::get_ipv6_multicast_loop(&s) {
Ok(multicast_loop) => assert!(multicast_loop),
Err(rustix::io::Errno::OPNOTSUPP) => (),
Err(rustix::io::Errno::INVAL) => (),
Err(rustix::io::Errno::NOPROTOOPT) => (),
Err(io::Errno::OPNOTSUPP) => (),
Err(io::Errno::INVAL) => (),
Err(io::Errno::NOPROTOOPT) => (),
Err(err) => Err(err).unwrap(),
}
assert_ne!(sockopt::get_ipv6_unicast_hops(&s).unwrap(), 0);
Expand All @@ -355,8 +381,8 @@ fn test_sockopts_ipv6() {
#[cfg(not(target_os = "netbsd"))]
match sockopt::get_ipv6_multicast_hops(&s) {
Ok(hops) => assert_eq!(hops, 0),
Err(rustix::io::Errno::NOPROTOOPT) => (),
Err(rustix::io::Errno::INVAL) => (),
Err(io::Errno::NOPROTOOPT) => (),
Err(io::Errno::INVAL) => (),
Err(err) => Err(err).unwrap(),
};

Expand All @@ -376,9 +402,9 @@ fn test_sockopts_ipv6() {
Err(err) => Err(err).unwrap(),
}
}
Err(rustix::io::Errno::OPNOTSUPP) => (),
Err(rustix::io::Errno::INVAL) => (),
Err(rustix::io::Errno::NOPROTOOPT) => (),
Err(io::Errno::OPNOTSUPP) => (),
Err(io::Errno::INVAL) => (),
Err(io::Errno::NOPROTOOPT) => (),
Err(err) => Err(err).unwrap(),
}

Expand Down Expand Up @@ -417,7 +443,7 @@ fn test_sockopts_ipv6() {
}

// Check the initial value of IPV6_TCLASS, set it, and check it.
#[cfg(not(solarish))]
#[cfg(not(any(solarish, target_os = "espidf", target_os = "haiku")))]
{
assert_eq!(sockopt::get_ipv6_tclass(&s).unwrap(), 0);
sockopt::set_ipv6_tclass(&s, 12).unwrap();
Expand All @@ -427,10 +453,10 @@ fn test_sockopts_ipv6() {
// Check that we can query IP6T_SO_ORIGINAL_DST.
#[cfg(linux_kernel)]
{
assert_eq!(
assert!(matches!(
sockopt::get_ipv6_original_dst(&s),
Err(io::Errno::NOPROTOOPT)
);
Err(io::Errno::NOENT | io::Errno::NOPROTOOPT)
));
}

test_sockopts_tcp(&s);
Expand Down

0 comments on commit 7d1c57f

Please sign in to comment.