1b8a62b91Sopenharmony_ci//! IPv4, IPv6, and Socket addresses. 2b8a62b91Sopenharmony_ci 3b8a62b91Sopenharmony_ciuse super::super::c; 4b8a62b91Sopenharmony_ci#[cfg(unix)] 5b8a62b91Sopenharmony_ciuse crate::ffi::CStr; 6b8a62b91Sopenharmony_ci#[cfg(unix)] 7b8a62b91Sopenharmony_ciuse crate::io; 8b8a62b91Sopenharmony_ci#[cfg(unix)] 9b8a62b91Sopenharmony_ciuse crate::path; 10b8a62b91Sopenharmony_ci#[cfg(not(windows))] 11b8a62b91Sopenharmony_ciuse core::convert::TryInto; 12b8a62b91Sopenharmony_ci#[cfg(unix)] 13b8a62b91Sopenharmony_ciuse core::fmt; 14b8a62b91Sopenharmony_ci#[cfg(unix)] 15b8a62b91Sopenharmony_ciuse core::slice; 16b8a62b91Sopenharmony_ci 17b8a62b91Sopenharmony_ci/// `struct sockaddr_un` 18b8a62b91Sopenharmony_ci#[cfg(unix)] 19b8a62b91Sopenharmony_ci#[derive(Clone)] 20b8a62b91Sopenharmony_ci#[doc(alias = "sockaddr_un")] 21b8a62b91Sopenharmony_cipub struct SocketAddrUnix { 22b8a62b91Sopenharmony_ci pub(crate) unix: c::sockaddr_un, 23b8a62b91Sopenharmony_ci #[cfg(not(any( 24b8a62b91Sopenharmony_ci target_os = "dragonfly", 25b8a62b91Sopenharmony_ci target_os = "freebsd", 26b8a62b91Sopenharmony_ci target_os = "ios", 27b8a62b91Sopenharmony_ci target_os = "macos", 28b8a62b91Sopenharmony_ci target_os = "netbsd", 29b8a62b91Sopenharmony_ci target_os = "openbsd", 30b8a62b91Sopenharmony_ci )))] 31b8a62b91Sopenharmony_ci len: c::socklen_t, 32b8a62b91Sopenharmony_ci} 33b8a62b91Sopenharmony_ci 34b8a62b91Sopenharmony_ci#[cfg(unix)] 35b8a62b91Sopenharmony_ciimpl SocketAddrUnix { 36b8a62b91Sopenharmony_ci /// Construct a new Unix-domain address from a filesystem path. 37b8a62b91Sopenharmony_ci #[inline] 38b8a62b91Sopenharmony_ci pub fn new<P: path::Arg>(path: P) -> io::Result<Self> { 39b8a62b91Sopenharmony_ci path.into_with_c_str(Self::_new) 40b8a62b91Sopenharmony_ci } 41b8a62b91Sopenharmony_ci 42b8a62b91Sopenharmony_ci #[inline] 43b8a62b91Sopenharmony_ci fn _new(path: &CStr) -> io::Result<Self> { 44b8a62b91Sopenharmony_ci let mut unix = Self::init(); 45b8a62b91Sopenharmony_ci let bytes = path.to_bytes_with_nul(); 46b8a62b91Sopenharmony_ci if bytes.len() > unix.sun_path.len() { 47b8a62b91Sopenharmony_ci return Err(io::Errno::NAMETOOLONG); 48b8a62b91Sopenharmony_ci } 49b8a62b91Sopenharmony_ci for (i, b) in bytes.iter().enumerate() { 50b8a62b91Sopenharmony_ci unix.sun_path[i] = *b as c::c_char; 51b8a62b91Sopenharmony_ci } 52b8a62b91Sopenharmony_ci 53b8a62b91Sopenharmony_ci #[cfg(any( 54b8a62b91Sopenharmony_ci target_os = "dragonfly", 55b8a62b91Sopenharmony_ci target_os = "freebsd", 56b8a62b91Sopenharmony_ci target_os = "ios", 57b8a62b91Sopenharmony_ci target_os = "macos", 58b8a62b91Sopenharmony_ci target_os = "netbsd", 59b8a62b91Sopenharmony_ci target_os = "openbsd", 60b8a62b91Sopenharmony_ci ))] 61b8a62b91Sopenharmony_ci { 62b8a62b91Sopenharmony_ci unix.sun_len = (offsetof_sun_path() + bytes.len()).try_into().unwrap(); 63b8a62b91Sopenharmony_ci } 64b8a62b91Sopenharmony_ci 65b8a62b91Sopenharmony_ci Ok(Self { 66b8a62b91Sopenharmony_ci unix, 67b8a62b91Sopenharmony_ci #[cfg(not(any( 68b8a62b91Sopenharmony_ci target_os = "dragonfly", 69b8a62b91Sopenharmony_ci target_os = "freebsd", 70b8a62b91Sopenharmony_ci target_os = "ios", 71b8a62b91Sopenharmony_ci target_os = "macos", 72b8a62b91Sopenharmony_ci target_os = "netbsd", 73b8a62b91Sopenharmony_ci target_os = "openbsd", 74b8a62b91Sopenharmony_ci )))] 75b8a62b91Sopenharmony_ci len: (offsetof_sun_path() + bytes.len()).try_into().unwrap(), 76b8a62b91Sopenharmony_ci }) 77b8a62b91Sopenharmony_ci } 78b8a62b91Sopenharmony_ci 79b8a62b91Sopenharmony_ci /// Construct a new abstract Unix-domain address from a byte slice. 80b8a62b91Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "linux"))] 81b8a62b91Sopenharmony_ci #[inline] 82b8a62b91Sopenharmony_ci pub fn new_abstract_name(name: &[u8]) -> io::Result<Self> { 83b8a62b91Sopenharmony_ci let mut unix = Self::init(); 84b8a62b91Sopenharmony_ci if 1 + name.len() > unix.sun_path.len() { 85b8a62b91Sopenharmony_ci return Err(io::Errno::NAMETOOLONG); 86b8a62b91Sopenharmony_ci } 87b8a62b91Sopenharmony_ci unix.sun_path[0] = b'\0' as c::c_char; 88b8a62b91Sopenharmony_ci for (i, b) in name.iter().enumerate() { 89b8a62b91Sopenharmony_ci unix.sun_path[1 + i] = *b as c::c_char; 90b8a62b91Sopenharmony_ci } 91b8a62b91Sopenharmony_ci let len = offsetof_sun_path() + 1 + name.len(); 92b8a62b91Sopenharmony_ci let len = len.try_into().unwrap(); 93b8a62b91Sopenharmony_ci Ok(Self { 94b8a62b91Sopenharmony_ci unix, 95b8a62b91Sopenharmony_ci #[cfg(not(any( 96b8a62b91Sopenharmony_ci target_os = "dragonfly", 97b8a62b91Sopenharmony_ci target_os = "freebsd", 98b8a62b91Sopenharmony_ci target_os = "ios", 99b8a62b91Sopenharmony_ci target_os = "macos", 100b8a62b91Sopenharmony_ci target_os = "netbsd", 101b8a62b91Sopenharmony_ci target_os = "openbsd", 102b8a62b91Sopenharmony_ci )))] 103b8a62b91Sopenharmony_ci len, 104b8a62b91Sopenharmony_ci }) 105b8a62b91Sopenharmony_ci } 106b8a62b91Sopenharmony_ci 107b8a62b91Sopenharmony_ci fn init() -> c::sockaddr_un { 108b8a62b91Sopenharmony_ci c::sockaddr_un { 109b8a62b91Sopenharmony_ci #[cfg(any( 110b8a62b91Sopenharmony_ci target_os = "dragonfly", 111b8a62b91Sopenharmony_ci target_os = "freebsd", 112b8a62b91Sopenharmony_ci target_os = "haiku", 113b8a62b91Sopenharmony_ci target_os = "ios", 114b8a62b91Sopenharmony_ci target_os = "macos", 115b8a62b91Sopenharmony_ci target_os = "netbsd", 116b8a62b91Sopenharmony_ci target_os = "openbsd", 117b8a62b91Sopenharmony_ci ))] 118b8a62b91Sopenharmony_ci sun_len: 0, 119b8a62b91Sopenharmony_ci sun_family: c::AF_UNIX as _, 120b8a62b91Sopenharmony_ci #[cfg(any( 121b8a62b91Sopenharmony_ci target_os = "dragonfly", 122b8a62b91Sopenharmony_ci target_os = "freebsd", 123b8a62b91Sopenharmony_ci target_os = "ios", 124b8a62b91Sopenharmony_ci target_os = "macos", 125b8a62b91Sopenharmony_ci target_os = "netbsd", 126b8a62b91Sopenharmony_ci target_os = "openbsd", 127b8a62b91Sopenharmony_ci ))] 128b8a62b91Sopenharmony_ci sun_path: [0; 104], 129b8a62b91Sopenharmony_ci #[cfg(not(any( 130b8a62b91Sopenharmony_ci target_os = "dragonfly", 131b8a62b91Sopenharmony_ci target_os = "freebsd", 132b8a62b91Sopenharmony_ci target_os = "haiku", 133b8a62b91Sopenharmony_ci target_os = "ios", 134b8a62b91Sopenharmony_ci target_os = "macos", 135b8a62b91Sopenharmony_ci target_os = "netbsd", 136b8a62b91Sopenharmony_ci target_os = "openbsd", 137b8a62b91Sopenharmony_ci )))] 138b8a62b91Sopenharmony_ci sun_path: [0; 108], 139b8a62b91Sopenharmony_ci #[cfg(target_os = "haiku")] 140b8a62b91Sopenharmony_ci sun_path: [0; 126], 141b8a62b91Sopenharmony_ci } 142b8a62b91Sopenharmony_ci } 143b8a62b91Sopenharmony_ci 144b8a62b91Sopenharmony_ci /// For a filesystem path address, return the path. 145b8a62b91Sopenharmony_ci #[inline] 146b8a62b91Sopenharmony_ci pub fn path(&self) -> Option<&CStr> { 147b8a62b91Sopenharmony_ci let len = self.len(); 148b8a62b91Sopenharmony_ci if len != 0 && self.unix.sun_path[0] != b'\0' as c::c_char { 149b8a62b91Sopenharmony_ci let end = len as usize - offsetof_sun_path(); 150b8a62b91Sopenharmony_ci let bytes = &self.unix.sun_path[..end]; 151b8a62b91Sopenharmony_ci // Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`. And 152b8a62b91Sopenharmony_ci // `from_bytes_with_nul_unchecked` since the string is NUL-terminated. 153b8a62b91Sopenharmony_ci unsafe { 154b8a62b91Sopenharmony_ci Some(CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts( 155b8a62b91Sopenharmony_ci bytes.as_ptr().cast(), 156b8a62b91Sopenharmony_ci bytes.len(), 157b8a62b91Sopenharmony_ci ))) 158b8a62b91Sopenharmony_ci } 159b8a62b91Sopenharmony_ci } else { 160b8a62b91Sopenharmony_ci None 161b8a62b91Sopenharmony_ci } 162b8a62b91Sopenharmony_ci } 163b8a62b91Sopenharmony_ci 164b8a62b91Sopenharmony_ci /// For an abstract address, return the identifier. 165b8a62b91Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "linux"))] 166b8a62b91Sopenharmony_ci #[inline] 167b8a62b91Sopenharmony_ci pub fn abstract_name(&self) -> Option<&[u8]> { 168b8a62b91Sopenharmony_ci let len = self.len(); 169b8a62b91Sopenharmony_ci if len != 0 && self.unix.sun_path[0] == b'\0' as c::c_char { 170b8a62b91Sopenharmony_ci let end = len as usize - offsetof_sun_path(); 171b8a62b91Sopenharmony_ci let bytes = &self.unix.sun_path[1..end]; 172b8a62b91Sopenharmony_ci // Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`. 173b8a62b91Sopenharmony_ci unsafe { Some(slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len())) } 174b8a62b91Sopenharmony_ci } else { 175b8a62b91Sopenharmony_ci None 176b8a62b91Sopenharmony_ci } 177b8a62b91Sopenharmony_ci } 178b8a62b91Sopenharmony_ci 179b8a62b91Sopenharmony_ci #[inline] 180b8a62b91Sopenharmony_ci pub(crate) fn addr_len(&self) -> c::socklen_t { 181b8a62b91Sopenharmony_ci #[cfg(not(any( 182b8a62b91Sopenharmony_ci target_os = "dragonfly", 183b8a62b91Sopenharmony_ci target_os = "freebsd", 184b8a62b91Sopenharmony_ci target_os = "ios", 185b8a62b91Sopenharmony_ci target_os = "macos", 186b8a62b91Sopenharmony_ci target_os = "netbsd", 187b8a62b91Sopenharmony_ci target_os = "openbsd", 188b8a62b91Sopenharmony_ci )))] 189b8a62b91Sopenharmony_ci { 190b8a62b91Sopenharmony_ci self.len 191b8a62b91Sopenharmony_ci } 192b8a62b91Sopenharmony_ci #[cfg(any( 193b8a62b91Sopenharmony_ci target_os = "dragonfly", 194b8a62b91Sopenharmony_ci target_os = "freebsd", 195b8a62b91Sopenharmony_ci target_os = "ios", 196b8a62b91Sopenharmony_ci target_os = "macos", 197b8a62b91Sopenharmony_ci target_os = "netbsd", 198b8a62b91Sopenharmony_ci target_os = "openbsd", 199b8a62b91Sopenharmony_ci ))] 200b8a62b91Sopenharmony_ci { 201b8a62b91Sopenharmony_ci c::socklen_t::from(self.unix.sun_len) 202b8a62b91Sopenharmony_ci } 203b8a62b91Sopenharmony_ci } 204b8a62b91Sopenharmony_ci 205b8a62b91Sopenharmony_ci #[inline] 206b8a62b91Sopenharmony_ci pub(crate) fn len(&self) -> usize { 207b8a62b91Sopenharmony_ci self.addr_len() as usize 208b8a62b91Sopenharmony_ci } 209b8a62b91Sopenharmony_ci} 210b8a62b91Sopenharmony_ci 211b8a62b91Sopenharmony_ci#[cfg(unix)] 212b8a62b91Sopenharmony_ciimpl PartialEq for SocketAddrUnix { 213b8a62b91Sopenharmony_ci #[inline] 214b8a62b91Sopenharmony_ci fn eq(&self, other: &Self) -> bool { 215b8a62b91Sopenharmony_ci let self_len = self.len() - offsetof_sun_path(); 216b8a62b91Sopenharmony_ci let other_len = other.len() - offsetof_sun_path(); 217b8a62b91Sopenharmony_ci self.unix.sun_path[..self_len].eq(&other.unix.sun_path[..other_len]) 218b8a62b91Sopenharmony_ci } 219b8a62b91Sopenharmony_ci} 220b8a62b91Sopenharmony_ci 221b8a62b91Sopenharmony_ci#[cfg(unix)] 222b8a62b91Sopenharmony_ciimpl Eq for SocketAddrUnix {} 223b8a62b91Sopenharmony_ci 224b8a62b91Sopenharmony_ci#[cfg(unix)] 225b8a62b91Sopenharmony_ciimpl PartialOrd for SocketAddrUnix { 226b8a62b91Sopenharmony_ci #[inline] 227b8a62b91Sopenharmony_ci fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> { 228b8a62b91Sopenharmony_ci let self_len = self.len() - offsetof_sun_path(); 229b8a62b91Sopenharmony_ci let other_len = other.len() - offsetof_sun_path(); 230b8a62b91Sopenharmony_ci self.unix.sun_path[..self_len].partial_cmp(&other.unix.sun_path[..other_len]) 231b8a62b91Sopenharmony_ci } 232b8a62b91Sopenharmony_ci} 233b8a62b91Sopenharmony_ci 234b8a62b91Sopenharmony_ci#[cfg(unix)] 235b8a62b91Sopenharmony_ciimpl Ord for SocketAddrUnix { 236b8a62b91Sopenharmony_ci #[inline] 237b8a62b91Sopenharmony_ci fn cmp(&self, other: &Self) -> core::cmp::Ordering { 238b8a62b91Sopenharmony_ci let self_len = self.len() - offsetof_sun_path(); 239b8a62b91Sopenharmony_ci let other_len = other.len() - offsetof_sun_path(); 240b8a62b91Sopenharmony_ci self.unix.sun_path[..self_len].cmp(&other.unix.sun_path[..other_len]) 241b8a62b91Sopenharmony_ci } 242b8a62b91Sopenharmony_ci} 243b8a62b91Sopenharmony_ci 244b8a62b91Sopenharmony_ci#[cfg(unix)] 245b8a62b91Sopenharmony_ciimpl core::hash::Hash for SocketAddrUnix { 246b8a62b91Sopenharmony_ci #[inline] 247b8a62b91Sopenharmony_ci fn hash<H: core::hash::Hasher>(&self, state: &mut H) { 248b8a62b91Sopenharmony_ci let self_len = self.len() - offsetof_sun_path(); 249b8a62b91Sopenharmony_ci self.unix.sun_path[..self_len].hash(state) 250b8a62b91Sopenharmony_ci } 251b8a62b91Sopenharmony_ci} 252b8a62b91Sopenharmony_ci 253b8a62b91Sopenharmony_ci#[cfg(unix)] 254b8a62b91Sopenharmony_ciimpl fmt::Debug for SocketAddrUnix { 255b8a62b91Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 256b8a62b91Sopenharmony_ci if let Some(path) = self.path() { 257b8a62b91Sopenharmony_ci path.fmt(fmt) 258b8a62b91Sopenharmony_ci } else { 259b8a62b91Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "linux"))] 260b8a62b91Sopenharmony_ci if let Some(name) = self.abstract_name() { 261b8a62b91Sopenharmony_ci return name.fmt(fmt); 262b8a62b91Sopenharmony_ci } 263b8a62b91Sopenharmony_ci 264b8a62b91Sopenharmony_ci "(unnamed)".fmt(fmt) 265b8a62b91Sopenharmony_ci } 266b8a62b91Sopenharmony_ci } 267b8a62b91Sopenharmony_ci} 268b8a62b91Sopenharmony_ci 269b8a62b91Sopenharmony_ci/// `struct sockaddr_storage` as a raw struct. 270b8a62b91Sopenharmony_cipub type SocketAddrStorage = c::sockaddr_storage; 271b8a62b91Sopenharmony_ci 272b8a62b91Sopenharmony_ci/// Return the offset of the `sun_path` field of `sockaddr_un`. 273b8a62b91Sopenharmony_ci#[cfg(not(windows))] 274b8a62b91Sopenharmony_ci#[inline] 275b8a62b91Sopenharmony_cipub(crate) fn offsetof_sun_path() -> usize { 276b8a62b91Sopenharmony_ci let z = c::sockaddr_un { 277b8a62b91Sopenharmony_ci #[cfg(any( 278b8a62b91Sopenharmony_ci target_os = "dragonfly", 279b8a62b91Sopenharmony_ci target_os = "freebsd", 280b8a62b91Sopenharmony_ci target_os = "haiku", 281b8a62b91Sopenharmony_ci target_os = "ios", 282b8a62b91Sopenharmony_ci target_os = "macos", 283b8a62b91Sopenharmony_ci target_os = "netbsd", 284b8a62b91Sopenharmony_ci target_os = "openbsd", 285b8a62b91Sopenharmony_ci ))] 286b8a62b91Sopenharmony_ci sun_len: 0_u8, 287b8a62b91Sopenharmony_ci #[cfg(any( 288b8a62b91Sopenharmony_ci target_os = "dragonfly", 289b8a62b91Sopenharmony_ci target_os = "freebsd", 290b8a62b91Sopenharmony_ci target_os = "haiku", 291b8a62b91Sopenharmony_ci target_os = "ios", 292b8a62b91Sopenharmony_ci target_os = "macos", 293b8a62b91Sopenharmony_ci target_os = "netbsd", 294b8a62b91Sopenharmony_ci target_os = "openbsd", 295b8a62b91Sopenharmony_ci ))] 296b8a62b91Sopenharmony_ci sun_family: 0_u8, 297b8a62b91Sopenharmony_ci #[cfg(not(any( 298b8a62b91Sopenharmony_ci target_os = "dragonfly", 299b8a62b91Sopenharmony_ci target_os = "freebsd", 300b8a62b91Sopenharmony_ci target_os = "haiku", 301b8a62b91Sopenharmony_ci target_os = "ios", 302b8a62b91Sopenharmony_ci target_os = "macos", 303b8a62b91Sopenharmony_ci target_os = "netbsd", 304b8a62b91Sopenharmony_ci target_os = "openbsd", 305b8a62b91Sopenharmony_ci )))] 306b8a62b91Sopenharmony_ci sun_family: 0_u16, 307b8a62b91Sopenharmony_ci #[cfg(any( 308b8a62b91Sopenharmony_ci target_os = "dragonfly", 309b8a62b91Sopenharmony_ci target_os = "freebsd", 310b8a62b91Sopenharmony_ci target_os = "ios", 311b8a62b91Sopenharmony_ci target_os = "macos", 312b8a62b91Sopenharmony_ci target_os = "netbsd", 313b8a62b91Sopenharmony_ci target_os = "openbsd", 314b8a62b91Sopenharmony_ci ))] 315b8a62b91Sopenharmony_ci sun_path: [0; 104], 316b8a62b91Sopenharmony_ci #[cfg(not(any( 317b8a62b91Sopenharmony_ci target_os = "dragonfly", 318b8a62b91Sopenharmony_ci target_os = "freebsd", 319b8a62b91Sopenharmony_ci target_os = "haiku", 320b8a62b91Sopenharmony_ci target_os = "ios", 321b8a62b91Sopenharmony_ci target_os = "macos", 322b8a62b91Sopenharmony_ci target_os = "netbsd", 323b8a62b91Sopenharmony_ci target_os = "openbsd", 324b8a62b91Sopenharmony_ci )))] 325b8a62b91Sopenharmony_ci sun_path: [0; 108], 326b8a62b91Sopenharmony_ci #[cfg(target_os = "haiku")] 327b8a62b91Sopenharmony_ci sun_path: [0; 126], 328b8a62b91Sopenharmony_ci }; 329b8a62b91Sopenharmony_ci (crate::utils::as_ptr(&z.sun_path) as usize) - (crate::utils::as_ptr(&z) as usize) 330b8a62b91Sopenharmony_ci} 331