1 //! IPv4, IPv6, and Socket addresses.
5 //! Linux's IPv6 type contains a union.
10 use crate::{io, path}
;
11 use core
::convert
::TryInto
;
12 use core
::{fmt, slice}
;
14 /// `struct sockaddr_un`
16 #[doc(alias = "sockaddr_un")]
17 pub struct SocketAddrUnix
{
18 pub(crate) unix
: c
::sockaddr_un
,
23 /// Construct a new Unix-domain address from a filesystem path.
25 pub fn new
<P
: path
::Arg
>(path
: P
) -> io
::Result
<Self> {
26 path
.into_with_c_str(Self::_new
)
30 fn _new(path
: &CStr
) -> io
::Result
<Self> {
31 let mut unix
= Self::init();
32 let bytes
= path
.to_bytes_with_nul();
33 if bytes
.len() > unix
.sun_path
.len() {
34 return Err(io
::Errno
::NAMETOOLONG
);
36 for (i
, b
) in bytes
.iter().enumerate() {
37 unix
.sun_path
[i
] = *b
as c
::c_char
;
39 let len
= offsetof_sun_path() + bytes
.len();
40 let len
= len
.try_into().unwrap();
41 Ok(Self { unix, len }
)
44 /// Construct a new abstract Unix-domain address from a byte slice.
46 pub fn new_abstract_name(name
: &[u8]) -> io
::Result
<Self> {
47 let mut unix
= Self::init();
48 if 1 + name
.len() > unix
.sun_path
.len() {
49 return Err(io
::Errno
::NAMETOOLONG
);
51 unix
.sun_path
[0] = b'
\0'
as c
::c_char
;
52 for (i
, b
) in name
.iter().enumerate() {
53 unix
.sun_path
[1 + i
] = *b
as c
::c_char
;
55 let len
= offsetof_sun_path() + 1 + name
.len();
56 let len
= len
.try_into().unwrap();
57 Ok(Self { unix, len }
)
60 fn init() -> c
::sockaddr_un
{
62 sun_family
: c
::AF_UNIX
as _
,
67 /// For a filesystem path address, return the path.
69 pub fn path(&self) -> Option
<&CStr
> {
71 if len
!= 0 && self.unix
.sun_path
[0] != b'
\0'
as c
::c_char
{
72 let end
= len
as usize - offsetof_sun_path();
73 let bytes
= &self.unix
.sun_path
[..end
];
74 // Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`. And
75 // `from_bytes_with_nul_unchecked` since the string is NUL-terminated.
77 Some(CStr
::from_bytes_with_nul_unchecked(slice
::from_raw_parts(
78 bytes
.as_ptr().cast(),
87 /// For an abstract address, return the identifier.
89 pub fn abstract_name(&self) -> Option
<&[u8]> {
91 if len
!= 0 && self.unix
.sun_path
[0] == b'
\0'
as c
::c_char
{
92 let end
= len
as usize - offsetof_sun_path();
93 let bytes
= &self.unix
.sun_path
[1..end
];
94 // Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`.
95 unsafe { Some(slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len())) }
102 pub(crate) fn addr_len(&self) -> c
::socklen_t
{
107 pub(crate) fn len(&self) -> usize {
108 self.addr_len() as usize
112 impl PartialEq
for SocketAddrUnix
{
114 fn eq(&self, other
: &Self) -> bool
{
115 let self_len
= self.len() - offsetof_sun_path();
116 let other_len
= other
.len() - offsetof_sun_path();
117 self.unix
.sun_path
[..self_len
].eq(&other
.unix
.sun_path
[..other_len
])
121 impl Eq
for SocketAddrUnix {}
123 impl PartialOrd
for SocketAddrUnix
{
125 fn partial_cmp(&self, other
: &Self) -> Option
<core
::cmp
::Ordering
> {
126 let self_len
= self.len() - offsetof_sun_path();
127 let other_len
= other
.len() - offsetof_sun_path();
128 self.unix
.sun_path
[..self_len
].partial_cmp(&other
.unix
.sun_path
[..other_len
])
132 impl Ord
for SocketAddrUnix
{
134 fn cmp(&self, other
: &Self) -> core
::cmp
::Ordering
{
135 let self_len
= self.len() - offsetof_sun_path();
136 let other_len
= other
.len() - offsetof_sun_path();
137 self.unix
.sun_path
[..self_len
].cmp(&other
.unix
.sun_path
[..other_len
])
141 impl core
::hash
::Hash
for SocketAddrUnix
{
143 fn hash
<H
: core
::hash
::Hasher
>(&self, state
: &mut H
) {
144 let self_len
= self.len() - offsetof_sun_path();
145 self.unix
.sun_path
[..self_len
].hash(state
)
149 impl fmt
::Debug
for SocketAddrUnix
{
150 fn fmt(&self, fmt
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
151 if let Some(path
) = self.path() {
153 } else if let Some(name
) = self.abstract_name() {
161 /// `struct sockaddr_storage` as a raw struct.
162 pub type SocketAddrStorage
= c
::sockaddr
;
164 /// Return the offset of the `sun_path` field of `sockaddr_un`.
166 pub(crate) fn offsetof_sun_path() -> usize {
167 let z
= c
::sockaddr_un
{
171 (crate::utils
::as_ptr(&z
.sun_path
) as usize) - (crate::utils
::as_ptr(&z
) as usize)