diff options
Diffstat (limited to 'vendor/rustix/src/backend/libc/net/read_sockaddr.rs')
-rw-r--r-- | vendor/rustix/src/backend/libc/net/read_sockaddr.rs | 306 |
1 files changed, 0 insertions, 306 deletions
diff --git a/vendor/rustix/src/backend/libc/net/read_sockaddr.rs b/vendor/rustix/src/backend/libc/net/read_sockaddr.rs deleted file mode 100644 index 6da7a50..0000000 --- a/vendor/rustix/src/backend/libc/net/read_sockaddr.rs +++ /dev/null @@ -1,306 +0,0 @@ -//! The BSD sockets API requires us to read the `ss_family` field before we can -//! interpret the rest of a `sockaddr` produced by the kernel. - -#[cfg(unix)] -use super::addr::SocketAddrUnix; -use super::ext::{in6_addr_s6_addr, in_addr_s_addr, sockaddr_in6_sin6_scope_id}; -use crate::backend::c; -#[cfg(not(windows))] -use crate::ffi::CStr; -use crate::io; -use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrV4, SocketAddrV6}; -use core::mem::size_of; - -// This must match the header of `sockaddr`. -#[repr(C)] -struct sockaddr_header { - #[cfg(any( - bsd, - target_os = "aix", - target_os = "espidf", - target_os = "haiku", - target_os = "nto", - target_os = "vita" - ))] - sa_len: u8, - #[cfg(any( - bsd, - target_os = "aix", - target_os = "espidf", - target_os = "haiku", - target_os = "nto", - target_os = "vita" - ))] - ss_family: u8, - #[cfg(not(any( - bsd, - target_os = "aix", - target_os = "espidf", - target_os = "haiku", - target_os = "nto", - target_os = "vita" - )))] - ss_family: u16, -} - -/// Read the `ss_family` field from a socket address returned from the OS. -/// -/// # Safety -/// -/// `storage` must point to a valid socket address returned from the OS. -#[inline] -unsafe fn read_ss_family(storage: *const c::sockaddr_storage) -> u16 { - // Assert that we know the layout of `sockaddr`. - let _ = c::sockaddr { - #[cfg(any( - bsd, - target_os = "aix", - target_os = "espidf", - target_os = "haiku", - target_os = "nto", - target_os = "vita" - ))] - sa_len: 0_u8, - #[cfg(any( - bsd, - target_os = "aix", - target_os = "espidf", - target_os = "haiku", - target_os = "nto", - target_os = "vita" - ))] - sa_family: 0_u8, - #[cfg(not(any( - bsd, - target_os = "aix", - target_os = "espidf", - target_os = "haiku", - target_os = "nto", - target_os = "vita" - )))] - sa_family: 0_u16, - #[cfg(not(target_os = "haiku"))] - sa_data: [0; 14], - #[cfg(target_os = "haiku")] - sa_data: [0; 30], - }; - - (*storage.cast::<sockaddr_header>()).ss_family.into() -} - -/// Set the `ss_family` field of a socket address to `AF_UNSPEC`, so that we -/// can test for `AF_UNSPEC` to test whether it was stored to. -pub(crate) unsafe fn initialize_family_to_unspec(storage: *mut c::sockaddr_storage) { - (*storage.cast::<sockaddr_header>()).ss_family = c::AF_UNSPEC as _; -} - -/// Read a socket address encoded in a platform-specific format. -/// -/// # Safety -/// -/// `storage` must point to valid socket address storage. -pub(crate) unsafe fn read_sockaddr( - storage: *const c::sockaddr_storage, - len: usize, -) -> io::Result<SocketAddrAny> { - #[cfg(unix)] - let offsetof_sun_path = super::addr::offsetof_sun_path(); - - if len < size_of::<c::sa_family_t>() { - return Err(io::Errno::INVAL); - } - match read_ss_family(storage).into() { - c::AF_INET => { - if len < size_of::<c::sockaddr_in>() { - return Err(io::Errno::INVAL); - } - let decode = &*storage.cast::<c::sockaddr_in>(); - Ok(SocketAddrAny::V4(SocketAddrV4::new( - Ipv4Addr::from(u32::from_be(in_addr_s_addr(decode.sin_addr))), - u16::from_be(decode.sin_port), - ))) - } - c::AF_INET6 => { - if len < size_of::<c::sockaddr_in6>() { - return Err(io::Errno::INVAL); - } - let decode = &*storage.cast::<c::sockaddr_in6>(); - #[cfg(not(windows))] - let s6_addr = decode.sin6_addr.s6_addr; - #[cfg(windows)] - let s6_addr = decode.sin6_addr.u.Byte; - #[cfg(not(windows))] - let sin6_scope_id = decode.sin6_scope_id; - #[cfg(windows)] - let sin6_scope_id = decode.Anonymous.sin6_scope_id; - Ok(SocketAddrAny::V6(SocketAddrV6::new( - Ipv6Addr::from(s6_addr), - u16::from_be(decode.sin6_port), - u32::from_be(decode.sin6_flowinfo), - sin6_scope_id, - ))) - } - #[cfg(unix)] - c::AF_UNIX => { - if len < offsetof_sun_path { - return Err(io::Errno::INVAL); - } - if len == offsetof_sun_path { - SocketAddrUnix::new(&[][..]).map(SocketAddrAny::Unix) - } else { - let decode = &*storage.cast::<c::sockaddr_un>(); - - // On Linux check for Linux's [abstract namespace]. - // - // [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html - #[cfg(linux_kernel)] - if decode.sun_path[0] == 0 { - return SocketAddrUnix::new_abstract_name(core::mem::transmute::< - &[c::c_char], - &[u8], - >( - &decode.sun_path[1..len - offsetof_sun_path], - )) - .map(SocketAddrAny::Unix); - } - - // Otherwise we expect a NUL-terminated filesystem path. - - // Trim off unused bytes from the end of `path_bytes`. - let path_bytes = if cfg!(any(solarish, target_os = "freebsd")) { - // FreeBSD and illumos sometimes set the length to longer - // than the length of the NUL-terminated string. Find the - // NUL and truncate the string accordingly. - &decode.sun_path[..decode - .sun_path - .iter() - .position(|b| *b == 0) - .ok_or(io::Errno::INVAL)?] - } else { - // Otherwise, use the provided length. - let provided_len = len - 1 - offsetof_sun_path; - if decode.sun_path[provided_len] != 0 { - return Err(io::Errno::INVAL); - } - debug_assert_eq!( - CStr::from_ptr(decode.sun_path.as_ptr()).to_bytes().len(), - provided_len - ); - &decode.sun_path[..provided_len] - }; - - SocketAddrUnix::new(core::mem::transmute::<&[c::c_char], &[u8]>(path_bytes)) - .map(SocketAddrAny::Unix) - } - } - _ => Err(io::Errno::INVAL), - } -} - -/// Read an optional socket address returned from the OS. -/// -/// # Safety -/// -/// `storage` must point to a valid socket address returned from the OS. -pub(crate) unsafe fn maybe_read_sockaddr_os( - storage: *const c::sockaddr_storage, - len: usize, -) -> Option<SocketAddrAny> { - if len == 0 { - return None; - } - - assert!(len >= size_of::<c::sa_family_t>()); - let family = read_ss_family(storage).into(); - if family == c::AF_UNSPEC { - None - } else { - Some(inner_read_sockaddr_os(family, storage, len)) - } -} - -/// Read a socket address returned from the OS. -/// -/// # Safety -/// -/// `storage` must point to a valid socket address returned from the OS. -pub(crate) unsafe fn read_sockaddr_os( - storage: *const c::sockaddr_storage, - len: usize, -) -> SocketAddrAny { - assert!(len >= size_of::<c::sa_family_t>()); - let family = read_ss_family(storage).into(); - inner_read_sockaddr_os(family, storage, len) -} - -unsafe fn inner_read_sockaddr_os( - family: c::c_int, - storage: *const c::sockaddr_storage, - len: usize, -) -> SocketAddrAny { - #[cfg(unix)] - let offsetof_sun_path = super::addr::offsetof_sun_path(); - - assert!(len >= size_of::<c::sa_family_t>()); - match family { - c::AF_INET => { - assert!(len >= size_of::<c::sockaddr_in>()); - let decode = &*storage.cast::<c::sockaddr_in>(); - SocketAddrAny::V4(SocketAddrV4::new( - Ipv4Addr::from(u32::from_be(in_addr_s_addr(decode.sin_addr))), - u16::from_be(decode.sin_port), - )) - } - c::AF_INET6 => { - assert!(len >= size_of::<c::sockaddr_in6>()); - let decode = &*storage.cast::<c::sockaddr_in6>(); - SocketAddrAny::V6(SocketAddrV6::new( - Ipv6Addr::from(in6_addr_s6_addr(decode.sin6_addr)), - u16::from_be(decode.sin6_port), - u32::from_be(decode.sin6_flowinfo), - sockaddr_in6_sin6_scope_id(decode), - )) - } - #[cfg(unix)] - c::AF_UNIX => { - assert!(len >= offsetof_sun_path); - if len == offsetof_sun_path { - SocketAddrAny::Unix(SocketAddrUnix::new(&[][..]).unwrap()) - } else { - let decode = &*storage.cast::<c::sockaddr_un>(); - - // On Linux check for Linux's [abstract namespace]. - // - // [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html - #[cfg(linux_kernel)] - if decode.sun_path[0] == 0 { - return SocketAddrAny::Unix( - SocketAddrUnix::new_abstract_name(core::mem::transmute::< - &[c::c_char], - &[u8], - >( - &decode.sun_path[1..len - offsetof_sun_path], - )) - .unwrap(), - ); - } - - // Otherwise we expect a NUL-terminated filesystem path. - assert_eq!(decode.sun_path[len - 1 - offsetof_sun_path], 0); - let path_bytes = &decode.sun_path[..len - 1 - offsetof_sun_path]; - - // FreeBSD and illumos sometimes set the length to longer than - // the length of the NUL-terminated string. Find the NUL and - // truncate the string accordingly. - #[cfg(any(solarish, target_os = "freebsd"))] - let path_bytes = &path_bytes[..path_bytes.iter().position(|b| *b == 0).unwrap()]; - - SocketAddrAny::Unix( - SocketAddrUnix::new(core::mem::transmute::<&[c::c_char], &[u8]>(path_bytes)) - .unwrap(), - ) - } - } - other => unimplemented!("{:?}", other), - } -} |