• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #[cfg(any(
2     bsd,
3     linux_android,
4     solarish,
5     target_os = "haiku",
6     target_os = "fuchsia",
7     target_os = "aix",
8 ))]
9 #[cfg(feature = "net")]
10 pub use self::datalink::LinkAddr;
11 #[cfg(any(linux_android, apple_targets))]
12 pub use self::vsock::VsockAddr;
13 use super::sa_family_t;
14 use crate::errno::Errno;
15 #[cfg(linux_android)]
16 use crate::sys::socket::addr::alg::AlgAddr;
17 #[cfg(linux_android)]
18 use crate::sys::socket::addr::netlink::NetlinkAddr;
19 #[cfg(all(feature = "ioctl", apple_targets))]
20 use crate::sys::socket::addr::sys_control::SysControlAddr;
21 use crate::{NixPath, Result};
22 use cfg_if::cfg_if;
23 use memoffset::offset_of;
24 use std::convert::TryInto;
25 use std::ffi::OsStr;
26 use std::hash::{Hash, Hasher};
27 use std::net::{Ipv4Addr, Ipv6Addr};
28 use std::os::unix::ffi::OsStrExt;
29 use std::path::Path;
30 use std::{fmt, mem, net, ptr, slice};
31 
32 /// Convert a std::net::Ipv4Addr into the libc form.
33 #[cfg(feature = "net")]
ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr34 pub(crate) const fn ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr {
35     libc::in_addr {
36         s_addr: u32::from_ne_bytes(addr.octets()),
37     }
38 }
39 
40 /// Convert a std::net::Ipv6Addr into the libc form.
41 #[cfg(feature = "net")]
ipv6addr_to_libc(addr: &net::Ipv6Addr) -> libc::in6_addr42 pub(crate) const fn ipv6addr_to_libc(addr: &net::Ipv6Addr) -> libc::in6_addr {
43     libc::in6_addr {
44         s6_addr: addr.octets(),
45     }
46 }
47 
48 /// These constants specify the protocol family to be used
49 /// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
50 ///
51 /// # References
52 ///
53 /// [address_families(7)](https://man7.org/linux/man-pages/man7/address_families.7.html)
54 // Should this be u8?
55 #[repr(i32)]
56 #[non_exhaustive]
57 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
58 pub enum AddressFamily {
59     /// Local communication (see [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html))
60     Unix = libc::AF_UNIX,
61     /// IPv4 Internet protocols (see [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html))
62     Inet = libc::AF_INET,
63     /// IPv6 Internet protocols (see [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html))
64     Inet6 = libc::AF_INET6,
65     /// Kernel user interface device (see [`netlink(7)`](https://man7.org/linux/man-pages/man7/netlink.7.html))
66     #[cfg(linux_android)]
67     Netlink = libc::AF_NETLINK,
68     /// Kernel interface for interacting with the routing table
69     #[cfg(not(any(linux_android, target_os = "redox")))]
70     Route = libc::PF_ROUTE,
71     /// Low level packet interface (see [`packet(7)`](https://man7.org/linux/man-pages/man7/packet.7.html))
72     #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
73     Packet = libc::AF_PACKET,
74     /// KEXT Controls and Notifications
75     #[cfg(apple_targets)]
76     System = libc::AF_SYSTEM,
77     /// Amateur radio AX.25 protocol
78     #[cfg(linux_android)]
79     Ax25 = libc::AF_AX25,
80     /// IPX - Novell protocols
81     #[cfg(not(any(target_os = "aix", target_os = "redox")))]
82     Ipx = libc::AF_IPX,
83     /// AppleTalk
84     #[cfg(not(target_os = "redox"))]
85     AppleTalk = libc::AF_APPLETALK,
86     /// AX.25 packet layer protocol.
87     /// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/))
88     #[cfg(linux_android)]
89     NetRom = libc::AF_NETROM,
90     /// Can't be used for creating sockets; mostly used for bridge
91     /// links in
92     /// [rtnetlink(7)](https://man7.org/linux/man-pages/man7/rtnetlink.7.html)
93     /// protocol commands.
94     #[cfg(linux_android)]
95     Bridge = libc::AF_BRIDGE,
96     /// Access to raw ATM PVCs
97     #[cfg(linux_android)]
98     AtmPvc = libc::AF_ATMPVC,
99     /// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](https://man7.org/linux/man-pages/man7/x25.7.html))
100     #[cfg(linux_android)]
101     X25 = libc::AF_X25,
102     /// RATS (Radio Amateur Telecommunications Society) Open
103     /// Systems environment (ROSE) AX.25 packet layer protocol.
104     /// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/))
105     #[cfg(linux_android)]
106     Rose = libc::AF_ROSE,
107     /// DECet protocol sockets.
108     #[cfg(not(any(target_os = "haiku", target_os = "redox")))]
109     Decnet = libc::AF_DECnet,
110     /// Reserved for "802.2LLC project"; never used.
111     #[cfg(linux_android)]
112     NetBeui = libc::AF_NETBEUI,
113     /// This was a short-lived (between Linux 2.1.30 and
114     /// 2.1.99pre2) protocol family for firewall upcalls.
115     #[cfg(linux_android)]
116     Security = libc::AF_SECURITY,
117     /// Key management protocol.
118     #[cfg(linux_android)]
119     Key = libc::AF_KEY,
120     #[allow(missing_docs)] // Not documented anywhere that I can find
121     #[cfg(linux_android)]
122     Ash = libc::AF_ASH,
123     /// Acorn Econet protocol
124     #[cfg(linux_android)]
125     Econet = libc::AF_ECONET,
126     /// Access to ATM Switched Virtual Circuits
127     #[cfg(linux_android)]
128     AtmSvc = libc::AF_ATMSVC,
129     /// Reliable Datagram Sockets (RDS) protocol
130     #[cfg(linux_android)]
131     Rds = libc::AF_RDS,
132     /// IBM SNA
133     #[cfg(not(any(target_os = "haiku", target_os = "redox")))]
134     Sna = libc::AF_SNA,
135     /// Socket interface over IrDA
136     #[cfg(linux_android)]
137     Irda = libc::AF_IRDA,
138     /// Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE)
139     #[cfg(linux_android)]
140     Pppox = libc::AF_PPPOX,
141     /// Legacy protocol for wide area network (WAN) connectivity that was used
142     /// by Sangoma WAN cards
143     #[cfg(linux_android)]
144     Wanpipe = libc::AF_WANPIPE,
145     /// Logical link control (IEEE 802.2 LLC) protocol
146     #[cfg(linux_android)]
147     Llc = libc::AF_LLC,
148     /// InfiniBand native addressing
149     #[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
150     Ib = libc::AF_IB,
151     /// Multiprotocol Label Switching
152     #[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
153     Mpls = libc::AF_MPLS,
154     /// Controller Area Network automotive bus protocol
155     #[cfg(linux_android)]
156     Can = libc::AF_CAN,
157     /// TIPC, "cluster domain sockets" protocol
158     #[cfg(linux_android)]
159     Tipc = libc::AF_TIPC,
160     /// Bluetooth low-level socket protocol
161     #[cfg(not(any(
162         target_os = "aix",
163         solarish,
164         apple_targets,
165         target_os = "hurd",
166         target_os = "redox",
167     )))]
168     Bluetooth = libc::AF_BLUETOOTH,
169     /// IUCV (inter-user communication vehicle) z/VM protocol for
170     /// hypervisor-guest interaction
171     #[cfg(linux_android)]
172     Iucv = libc::AF_IUCV,
173     /// Rx, Andrew File System remote procedure call protocol
174     #[cfg(linux_android)]
175     RxRpc = libc::AF_RXRPC,
176     /// New "modular ISDN" driver interface protocol
177     #[cfg(not(any(
178         target_os = "aix",
179         solarish,
180         target_os = "haiku",
181         target_os = "hurd",
182         target_os = "redox",
183     )))]
184     Isdn = libc::AF_ISDN,
185     /// Nokia cellular modem IPC/RPC interface
186     #[cfg(linux_android)]
187     Phonet = libc::AF_PHONET,
188     /// IEEE 802.15.4 WPAN (wireless personal area network) raw packet protocol
189     #[cfg(linux_android)]
190     Ieee802154 = libc::AF_IEEE802154,
191     /// Ericsson's Communication CPU to Application CPU interface (CAIF)
192     /// protocol.
193     #[cfg(linux_android)]
194     Caif = libc::AF_CAIF,
195     /// Interface to kernel crypto API
196     #[cfg(linux_android)]
197     Alg = libc::AF_ALG,
198     /// Near field communication
199     #[cfg(target_os = "linux")]
200     Nfc = libc::AF_NFC,
201     /// VMWare VSockets protocol for hypervisor-guest interaction.
202     #[cfg(any(linux_android, apple_targets))]
203     Vsock = libc::AF_VSOCK,
204     /// ARPANet IMP addresses
205     #[cfg(bsd)]
206     ImpLink = libc::AF_IMPLINK,
207     /// PUP protocols, e.g. BSP
208     #[cfg(bsd)]
209     Pup = libc::AF_PUP,
210     /// MIT CHAOS protocols
211     #[cfg(bsd)]
212     Chaos = libc::AF_CHAOS,
213     /// Novell and Xerox protocol
214     #[cfg(any(apple_targets, netbsdlike))]
215     Ns = libc::AF_NS,
216     #[allow(missing_docs)] // Not documented anywhere that I can find
217     #[cfg(bsd)]
218     Iso = libc::AF_ISO,
219     /// Bell Labs virtual circuit switch ?
220     #[cfg(bsd)]
221     Datakit = libc::AF_DATAKIT,
222     /// CCITT protocols, X.25 etc
223     #[cfg(bsd)]
224     Ccitt = libc::AF_CCITT,
225     /// DEC Direct data link interface
226     #[cfg(bsd)]
227     Dli = libc::AF_DLI,
228     #[allow(missing_docs)] // Not documented anywhere that I can find
229     #[cfg(bsd)]
230     Lat = libc::AF_LAT,
231     /// NSC Hyperchannel
232     #[cfg(bsd)]
233     Hylink = libc::AF_HYLINK,
234     /// Link layer interface
235     #[cfg(any(bsd, solarish))]
236     Link = libc::AF_LINK,
237     /// connection-oriented IP, aka ST II
238     #[cfg(bsd)]
239     Coip = libc::AF_COIP,
240     /// Computer Network Technology
241     #[cfg(bsd)]
242     Cnt = libc::AF_CNT,
243     /// Native ATM access
244     #[cfg(bsd)]
245     Natm = libc::AF_NATM,
246     /// Unspecified address family, (see [`getaddrinfo(3)`](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html))
247     #[cfg(linux_android)]
248     Unspec = libc::AF_UNSPEC,
249 }
250 
251 impl AddressFamily {
252     /// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from
253     /// the `sa_family` field of a `sockaddr`.
254     ///
255     /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet
256     /// and System. Returns None for unsupported or unknown address families.
from_i32(family: i32) -> Option<AddressFamily>257     pub const fn from_i32(family: i32) -> Option<AddressFamily> {
258         match family {
259             libc::AF_UNIX => Some(AddressFamily::Unix),
260             libc::AF_INET => Some(AddressFamily::Inet),
261             libc::AF_INET6 => Some(AddressFamily::Inet6),
262             #[cfg(linux_android)]
263             libc::AF_NETLINK => Some(AddressFamily::Netlink),
264             #[cfg(apple_targets)]
265             libc::AF_SYSTEM => Some(AddressFamily::System),
266             #[cfg(not(any(linux_android, target_os = "redox")))]
267             libc::PF_ROUTE => Some(AddressFamily::Route),
268             #[cfg(linux_android)]
269             libc::AF_PACKET => Some(AddressFamily::Packet),
270             #[cfg(any(bsd, solarish))]
271             libc::AF_LINK => Some(AddressFamily::Link),
272             #[cfg(any(linux_android, apple_targets))]
273             libc::AF_VSOCK => Some(AddressFamily::Vsock),
274             _ => None,
275         }
276     }
277 }
278 
279 /// A wrapper around `sockaddr_un`.
280 #[derive(Clone, Copy, Debug)]
281 #[repr(C)]
282 pub struct UnixAddr {
283     // INVARIANT: sun & sun_len are valid as defined by docs for from_raw_parts
284     sun: libc::sockaddr_un,
285     /// The length of the valid part of `sun`, including the sun_family field
286     /// but excluding any trailing nul.
287     // On the BSDs, this field is built into sun
288     #[cfg(not(any(bsd, target_os = "haiku", target_os = "hurd")))]
289     sun_len: u8,
290 }
291 
292 // linux man page unix(7) says there are 3 kinds of unix socket:
293 // pathname: addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1
294 // unnamed: addrlen = sizeof(sa_family_t)
295 // abstract: addren > sizeof(sa_family_t), name = sun_path[..(addrlen - sizeof(sa_family_t))]
296 //
297 // what we call path_len = addrlen - offsetof(struct sockaddr_un, sun_path)
298 #[derive(PartialEq, Eq, Hash)]
299 enum UnixAddrKind<'a> {
300     Pathname(&'a Path),
301     Unnamed,
302     #[cfg(linux_android)]
303     Abstract(&'a [u8]),
304 }
305 impl<'a> UnixAddrKind<'a> {
306     /// Safety: sun & sun_len must be valid
307     #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms
get(sun: &'a libc::sockaddr_un, sun_len: u8) -> Self308     unsafe fn get(sun: &'a libc::sockaddr_un, sun_len: u8) -> Self {
309         assert!(sun_len as usize >= offset_of!(libc::sockaddr_un, sun_path));
310         let path_len =
311             sun_len as usize - offset_of!(libc::sockaddr_un, sun_path);
312         if path_len == 0 {
313             return Self::Unnamed;
314         }
315         #[cfg(linux_android)]
316         if sun.sun_path[0] == 0 {
317             let name = unsafe {
318                 slice::from_raw_parts(
319                     sun.sun_path.as_ptr().add(1).cast(),
320                     path_len - 1,
321                 )
322             };
323             return Self::Abstract(name);
324         }
325         let pathname = unsafe {
326             slice::from_raw_parts(sun.sun_path.as_ptr().cast(), path_len)
327         };
328         if pathname.last() == Some(&0) {
329             // A trailing NUL is not considered part of the path, and it does
330             // not need to be included in the addrlen passed to functions like
331             // bind().  However, Linux adds a trailing NUL, even if one was not
332             // originally present, when returning addrs from functions like
333             // getsockname() (the BSDs do not do that).  So we need to filter
334             // out any trailing NUL here, so sockaddrs can round-trip through
335             // the kernel and still compare equal.
336             Self::Pathname(Path::new(OsStr::from_bytes(
337                 &pathname[0..pathname.len() - 1],
338             )))
339         } else {
340             Self::Pathname(Path::new(OsStr::from_bytes(pathname)))
341         }
342     }
343 }
344 
345 impl UnixAddr {
346     /// Create a new sockaddr_un representing a filesystem path.
347     #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms
new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr>348     pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
349         path.with_nix_path(|cstr| unsafe {
350             let mut ret = libc::sockaddr_un {
351                 sun_family: AddressFamily::Unix as sa_family_t,
352                 ..mem::zeroed()
353             };
354 
355             let bytes = cstr.to_bytes();
356 
357             if bytes.len() >= ret.sun_path.len() {
358                 return Err(Errno::ENAMETOOLONG);
359             }
360 
361             let sun_len = (bytes.len()
362                 + offset_of!(libc::sockaddr_un, sun_path))
363             .try_into()
364             .unwrap();
365 
366             #[cfg(any(bsd, target_os = "haiku", target_os = "hurd"))]
367             {
368                 ret.sun_len = sun_len;
369             }
370             ptr::copy_nonoverlapping(
371                 bytes.as_ptr(),
372                 ret.sun_path.as_mut_ptr().cast(),
373                 bytes.len(),
374             );
375 
376             Ok(UnixAddr::from_raw_parts(ret, sun_len))
377         })?
378     }
379 
380     /// Create a new `sockaddr_un` representing an address in the "abstract namespace".
381     ///
382     /// The leading nul byte for the abstract namespace is automatically added;
383     /// thus the input `path` is expected to be the bare name, not NUL-prefixed.
384     /// This is a Linux-specific extension, primarily used to allow chrooted
385     /// processes to communicate with processes having a different filesystem view.
386     #[cfg(linux_android)]
387     #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms
new_abstract(path: &[u8]) -> Result<UnixAddr>388     pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
389         unsafe {
390             let mut ret = libc::sockaddr_un {
391                 sun_family: AddressFamily::Unix as sa_family_t,
392                 ..mem::zeroed()
393             };
394 
395             if path.len() >= ret.sun_path.len() {
396                 return Err(Errno::ENAMETOOLONG);
397             }
398             let sun_len =
399                 (path.len() + 1 + offset_of!(libc::sockaddr_un, sun_path))
400                     .try_into()
401                     .unwrap();
402 
403             // Abstract addresses are represented by sun_path[0] ==
404             // b'\0', so copy starting one byte in.
405             ptr::copy_nonoverlapping(
406                 path.as_ptr(),
407                 ret.sun_path.as_mut_ptr().offset(1).cast(),
408                 path.len(),
409             );
410 
411             Ok(UnixAddr::from_raw_parts(ret, sun_len))
412         }
413     }
414 
415     /// Create a new `sockaddr_un` representing an "unnamed" unix socket address.
416     #[cfg(linux_android)]
new_unnamed() -> UnixAddr417     pub fn new_unnamed() -> UnixAddr {
418         let ret = libc::sockaddr_un {
419             sun_family: AddressFamily::Unix as sa_family_t,
420             ..unsafe { mem::zeroed() }
421         };
422 
423         let sun_len: u8 =
424             offset_of!(libc::sockaddr_un, sun_path).try_into().unwrap();
425 
426         unsafe { UnixAddr::from_raw_parts(ret, sun_len) }
427     }
428 
429     /// Create a UnixAddr from a raw `sockaddr_un` struct and a size. `sun_len`
430     /// is the size of the valid portion of the struct, excluding any trailing
431     /// NUL.
432     ///
433     /// # Safety
434     /// This pair of sockaddr_un & sun_len must be a valid unix addr, which
435     /// means:
436     /// - sun_len >= offset_of(sockaddr_un, sun_path)
437     /// - sun_len <= sockaddr_un.sun_path.len() - offset_of(sockaddr_un, sun_path)
438     /// - if this is a unix addr with a pathname, sun.sun_path is a
439     ///   fs path, not necessarily nul-terminated.
from_raw_parts( sun: libc::sockaddr_un, sun_len: u8, ) -> UnixAddr440     pub(crate) unsafe fn from_raw_parts(
441         sun: libc::sockaddr_un,
442         sun_len: u8,
443     ) -> UnixAddr {
444         cfg_if! {
445             if #[cfg(any(linux_android,
446                      target_os = "fuchsia",
447                      solarish,
448                      target_os = "redox",
449                 ))]
450             {
451                 UnixAddr { sun, sun_len }
452             } else {
453                 assert_eq!(sun_len, sun.sun_len);
454                 UnixAddr {sun}
455             }
456         }
457     }
458 
kind(&self) -> UnixAddrKind<'_>459     fn kind(&self) -> UnixAddrKind<'_> {
460         // SAFETY: our sockaddr is always valid because of the invariant on the struct
461         unsafe { UnixAddrKind::get(&self.sun, self.sun_len()) }
462     }
463 
464     /// If this address represents a filesystem path, return that path.
path(&self) -> Option<&Path>465     pub fn path(&self) -> Option<&Path> {
466         match self.kind() {
467             UnixAddrKind::Pathname(path) => Some(path),
468             _ => None,
469         }
470     }
471 
472     /// If this address represents an abstract socket, return its name.
473     ///
474     /// For abstract sockets only the bare name is returned, without the
475     /// leading NUL byte. `None` is returned for unnamed or path-backed sockets.
476     #[cfg(linux_android)]
as_abstract(&self) -> Option<&[u8]>477     pub fn as_abstract(&self) -> Option<&[u8]> {
478         match self.kind() {
479             UnixAddrKind::Abstract(name) => Some(name),
480             _ => None,
481         }
482     }
483 
484     /// Check if this address is an "unnamed" unix socket address.
485     #[cfg(linux_android)]
486     #[inline]
is_unnamed(&self) -> bool487     pub fn is_unnamed(&self) -> bool {
488         matches!(self.kind(), UnixAddrKind::Unnamed)
489     }
490 
491     /// Returns the addrlen of this socket - `offsetof(struct sockaddr_un, sun_path)`
492     #[inline]
path_len(&self) -> usize493     pub fn path_len(&self) -> usize {
494         self.sun_len() as usize - offset_of!(libc::sockaddr_un, sun_path)
495     }
496     /// Returns a pointer to the raw `sockaddr_un` struct
497     #[inline]
as_ptr(&self) -> *const libc::sockaddr_un498     pub fn as_ptr(&self) -> *const libc::sockaddr_un {
499         &self.sun
500     }
501     /// Returns a mutable pointer to the raw `sockaddr_un` struct
502     #[inline]
as_mut_ptr(&mut self) -> *mut libc::sockaddr_un503     pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr_un {
504         &mut self.sun
505     }
506 
sun_len(&self) -> u8507     fn sun_len(&self) -> u8 {
508         cfg_if! {
509             if #[cfg(any(linux_android,
510                      target_os = "fuchsia",
511                      solarish,
512                      target_os = "redox",
513                 ))]
514             {
515                 self.sun_len
516             } else {
517                 self.sun.sun_len
518             }
519         }
520     }
521 }
522 
523 impl private::SockaddrLikePriv for UnixAddr {}
524 impl SockaddrLike for UnixAddr {
525     #[cfg(any(
526         linux_android,
527         target_os = "fuchsia",
528         solarish,
529         target_os = "redox"
530     ))]
len(&self) -> libc::socklen_t531     fn len(&self) -> libc::socklen_t {
532         self.sun_len.into()
533     }
534 
from_raw( addr: *const libc::sockaddr, len: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,535     unsafe fn from_raw(
536         addr: *const libc::sockaddr,
537         len: Option<libc::socklen_t>,
538     ) -> Option<Self>
539     where
540         Self: Sized,
541     {
542         if let Some(l) = len {
543             if (l as usize) < offset_of!(libc::sockaddr_un, sun_path)
544                 || l > u8::MAX as libc::socklen_t
545             {
546                 return None;
547             }
548         }
549         if unsafe { (*addr).sa_family as i32 != libc::AF_UNIX } {
550             return None;
551         }
552         let mut su: libc::sockaddr_un = unsafe { mem::zeroed() };
553         let sup = &mut su as *mut libc::sockaddr_un as *mut u8;
554         cfg_if! {
555             if #[cfg(any(linux_android,
556                          target_os = "fuchsia",
557                          solarish,
558                          target_os = "redox",
559                 ))] {
560                 let su_len = len.unwrap_or(
561                     mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
562                 );
563             } else {
564                 let su_len = unsafe { len.unwrap_or((*addr).sa_len as libc::socklen_t) };
565             }
566         }
567         unsafe { ptr::copy(addr as *const u8, sup, su_len as usize) };
568         Some(unsafe { Self::from_raw_parts(su, su_len as u8) })
569     }
570 
size() -> libc::socklen_t where Self: Sized,571     fn size() -> libc::socklen_t
572     where
573         Self: Sized,
574     {
575         mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
576     }
577 
set_length( &mut self, new_length: usize, ) -> std::result::Result<(), SocketAddressLengthNotDynamic>578     unsafe fn set_length(
579         &mut self,
580         new_length: usize,
581     ) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
582         // `new_length` is only used on some platforms, so it must be provided even when not used
583         #![allow(unused_variables)]
584         cfg_if! {
585             if #[cfg(any(linux_android,
586                          target_os = "fuchsia",
587                          solarish,
588                          target_os = "redox",
589                 ))] {
590                 self.sun_len = new_length as u8;
591             }
592         };
593         Ok(())
594     }
595 }
596 
597 impl AsRef<libc::sockaddr_un> for UnixAddr {
as_ref(&self) -> &libc::sockaddr_un598     fn as_ref(&self) -> &libc::sockaddr_un {
599         &self.sun
600     }
601 }
602 
603 #[cfg(linux_android)]
fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result604 fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
605     use fmt::Write;
606     f.write_str("@\"")?;
607     for &b in abs {
608         use fmt::Display;
609         char::from(b).escape_default().fmt(f)?;
610     }
611     f.write_char('"')?;
612     Ok(())
613 }
614 
615 impl fmt::Display for UnixAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result616     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
617         match self.kind() {
618             UnixAddrKind::Pathname(path) => path.display().fmt(f),
619             UnixAddrKind::Unnamed => f.pad("<unbound UNIX socket>"),
620             #[cfg(linux_android)]
621             UnixAddrKind::Abstract(name) => fmt_abstract(name, f),
622         }
623     }
624 }
625 
626 impl PartialEq for UnixAddr {
eq(&self, other: &UnixAddr) -> bool627     fn eq(&self, other: &UnixAddr) -> bool {
628         self.kind() == other.kind()
629     }
630 }
631 
632 impl Eq for UnixAddr {}
633 
634 impl Hash for UnixAddr {
hash<H: Hasher>(&self, s: &mut H)635     fn hash<H: Hasher>(&self, s: &mut H) {
636         self.kind().hash(s)
637     }
638 }
639 
640 /// Anything that, in C, can be cast back and forth to `sockaddr`.
641 ///
642 /// Most implementors also implement `AsRef<libc::XXX>` to access their
643 /// inner type read-only.
644 #[allow(clippy::len_without_is_empty)]
645 pub trait SockaddrLike: private::SockaddrLikePriv {
646     /// Returns a raw pointer to the inner structure.  Useful for FFI.
as_ptr(&self) -> *const libc::sockaddr647     fn as_ptr(&self) -> *const libc::sockaddr {
648         self as *const Self as *const libc::sockaddr
649     }
650 
651     /// Unsafe constructor from a variable length source
652     ///
653     /// Some C APIs from provide `len`, and others do not.  If it's provided it
654     /// will be validated.  If not, it will be guessed based on the family.
655     ///
656     /// # Arguments
657     ///
658     /// - `addr`:   raw pointer to something that can be cast to a
659     ///             `libc::sockaddr`. For example, `libc::sockaddr_in`,
660     ///             `libc::sockaddr_in6`, etc.
661     /// - `len`:    For fixed-width types like `sockaddr_in`, it will be
662     ///             validated if present and ignored if not.  For variable-width
663     ///             types it is required and must be the total length of valid
664     ///             data.  For example, if `addr` points to a
665     ///             named `sockaddr_un`, then `len` must be the length of the
666     ///             structure up to but not including the trailing NUL.
667     ///
668     /// # Safety
669     ///
670     /// `addr` must be valid for the specific type of sockaddr.  `len`, if
671     /// present, must not exceed the length of valid data in `addr`.
from_raw( addr: *const libc::sockaddr, len: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized672     unsafe fn from_raw(
673         addr: *const libc::sockaddr,
674         len: Option<libc::socklen_t>,
675     ) -> Option<Self>
676     where
677         Self: Sized;
678 
679     /// Return the address family of this socket
680     ///
681     /// # Examples
682     /// One common use is to match on the family of a union type, like this:
683     /// ```
684     /// # use nix::sys::socket::*;
685     /// # use std::os::unix::io::AsRawFd;
686     /// let fd = socket(AddressFamily::Inet, SockType::Stream,
687     ///     SockFlag::empty(), None).unwrap();
688     /// let ss: SockaddrStorage = getsockname(fd.as_raw_fd()).unwrap();
689     /// match ss.family().unwrap() {
690     ///     AddressFamily::Inet => println!("{}", ss.as_sockaddr_in().unwrap()),
691     ///     AddressFamily::Inet6 => println!("{}", ss.as_sockaddr_in6().unwrap()),
692     ///     _ => println!("Unexpected address family")
693     /// }
694     /// ```
family(&self) -> Option<AddressFamily>695     fn family(&self) -> Option<AddressFamily> {
696         // Safe since all implementors have a sa_family field at the same
697         // address, and they're all repr(C)
698         AddressFamily::from_i32(unsafe {
699             (*(self as *const Self as *const libc::sockaddr)).sa_family as i32
700         })
701     }
702 
703     cfg_if! {
704         if #[cfg(bsd)] {
705             /// Return the length of valid data in the sockaddr structure.
706             ///
707             /// For fixed-size sockaddrs, this should be the size of the
708             /// structure.  But for variable-sized types like [`UnixAddr`] it
709             /// may be less.
710             fn len(&self) -> libc::socklen_t {
711                 // Safe since all implementors have a sa_len field at the same
712                 // address, and they're all repr(transparent).
713                 // Robust for all implementors.
714                 unsafe {
715                     (*(self as *const Self as *const libc::sockaddr)).sa_len
716                 }.into()
717             }
718         } else {
719             /// Return the length of valid data in the sockaddr structure.
720             ///
721             /// For fixed-size sockaddrs, this should be the size of the
722             /// structure.  But for variable-sized types like [`UnixAddr`] it
723             /// may be less.
724             fn len(&self) -> libc::socklen_t {
725                 // No robust default implementation is possible without an
726                 // sa_len field.  Implementors with a variable size must
727                 // override this method.
728                 mem::size_of_val(self) as libc::socklen_t
729             }
730         }
731     }
732 
733     /// Return the available space in the structure
size() -> libc::socklen_t where Self: Sized,734     fn size() -> libc::socklen_t
735     where
736         Self: Sized,
737     {
738         mem::size_of::<Self>() as libc::socklen_t
739     }
740 
741     /// Set the length of this socket address
742     ///
743     /// This method may only be called on socket addresses whose lengths are dynamic, and it
744     /// returns an error if called on a type whose length is static.
745     ///
746     /// # Safety
747     ///
748     /// `new_length` must be a valid length for this type of address. Specifically, reads of that
749     /// length from `self` must be valid.
750     #[doc(hidden)]
set_length( &mut self, _new_length: usize, ) -> std::result::Result<(), SocketAddressLengthNotDynamic>751     unsafe fn set_length(
752         &mut self,
753         _new_length: usize,
754     ) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
755         Err(SocketAddressLengthNotDynamic)
756     }
757 }
758 
759 /// The error returned by [`SockaddrLike::set_length`] on an address whose length is statically
760 /// fixed.
761 #[derive(Copy, Clone, Debug)]
762 pub struct SocketAddressLengthNotDynamic;
763 impl fmt::Display for SocketAddressLengthNotDynamic {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result764     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
765         f.write_str("Attempted to set length on socket whose length is statically fixed")
766     }
767 }
768 impl std::error::Error for SocketAddressLengthNotDynamic {}
769 
770 impl private::SockaddrLikePriv for () {
as_mut_ptr(&mut self) -> *mut libc::sockaddr771     fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
772         ptr::null_mut()
773     }
774 }
775 
776 /// `()` can be used in place of a real Sockaddr when no address is expected,
777 /// for example for a field of `Option<S> where S: SockaddrLike`.
778 // If this RFC ever stabilizes, then ! will be a better choice.
779 // https://github.com/rust-lang/rust/issues/35121
780 impl SockaddrLike for () {
as_ptr(&self) -> *const libc::sockaddr781     fn as_ptr(&self) -> *const libc::sockaddr {
782         ptr::null()
783     }
784 
from_raw( _: *const libc::sockaddr, _: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,785     unsafe fn from_raw(
786         _: *const libc::sockaddr,
787         _: Option<libc::socklen_t>,
788     ) -> Option<Self>
789     where
790         Self: Sized,
791     {
792         None
793     }
794 
family(&self) -> Option<AddressFamily>795     fn family(&self) -> Option<AddressFamily> {
796         None
797     }
798 
len(&self) -> libc::socklen_t799     fn len(&self) -> libc::socklen_t {
800         0
801     }
802 }
803 
804 /// An IPv4 socket address
805 #[cfg(feature = "net")]
806 #[repr(transparent)]
807 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
808 pub struct SockaddrIn(libc::sockaddr_in);
809 
810 #[cfg(feature = "net")]
811 impl SockaddrIn {
812     /// Returns the IP address associated with this socket address, in native
813     /// endian.
ip(&self) -> net::Ipv4Addr814     pub const fn ip(&self) -> net::Ipv4Addr {
815         let bytes = self.0.sin_addr.s_addr.to_ne_bytes();
816         let (a, b, c, d) = (bytes[0], bytes[1], bytes[2], bytes[3]);
817         Ipv4Addr::new(a, b, c, d)
818     }
819 
820     /// Creates a new socket address from IPv4 octets and a port number.
new(a: u8, b: u8, c: u8, d: u8, port: u16) -> Self821     pub fn new(a: u8, b: u8, c: u8, d: u8, port: u16) -> Self {
822         Self(libc::sockaddr_in {
823             #[cfg(any(
824                 bsd,
825                 target_os = "aix",
826                 target_os = "haiku",
827                 target_os = "hurd"
828             ))]
829             sin_len: Self::size() as u8,
830             sin_family: AddressFamily::Inet as sa_family_t,
831             sin_port: u16::to_be(port),
832             sin_addr: libc::in_addr {
833                 s_addr: u32::from_ne_bytes([a, b, c, d]),
834             },
835             sin_zero: unsafe { mem::zeroed() },
836         })
837     }
838 
839     /// Returns the port number associated with this socket address, in native
840     /// endian.
port(&self) -> u16841     pub const fn port(&self) -> u16 {
842         u16::from_be(self.0.sin_port)
843     }
844 }
845 
846 #[cfg(feature = "net")]
847 impl private::SockaddrLikePriv for SockaddrIn {}
848 #[cfg(feature = "net")]
849 impl SockaddrLike for SockaddrIn {
from_raw( addr: *const libc::sockaddr, len: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,850     unsafe fn from_raw(
851         addr: *const libc::sockaddr,
852         len: Option<libc::socklen_t>,
853     ) -> Option<Self>
854     where
855         Self: Sized,
856     {
857         if let Some(l) = len {
858             if l != mem::size_of::<libc::sockaddr_in>() as libc::socklen_t {
859                 return None;
860             }
861         }
862         if unsafe { (*addr).sa_family as i32 != libc::AF_INET } {
863             return None;
864         }
865         Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
866     }
867 }
868 
869 #[cfg(feature = "net")]
870 impl AsRef<libc::sockaddr_in> for SockaddrIn {
as_ref(&self) -> &libc::sockaddr_in871     fn as_ref(&self) -> &libc::sockaddr_in {
872         &self.0
873     }
874 }
875 
876 #[cfg(feature = "net")]
877 impl fmt::Display for SockaddrIn {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result878     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
879         let ne = u32::from_be(self.0.sin_addr.s_addr);
880         let port = u16::from_be(self.0.sin_port);
881         write!(
882             f,
883             "{}.{}.{}.{}:{}",
884             ne >> 24,
885             (ne >> 16) & 0xFF,
886             (ne >> 8) & 0xFF,
887             ne & 0xFF,
888             port
889         )
890     }
891 }
892 
893 #[cfg(feature = "net")]
894 impl From<net::SocketAddrV4> for SockaddrIn {
from(addr: net::SocketAddrV4) -> Self895     fn from(addr: net::SocketAddrV4) -> Self {
896         Self(libc::sockaddr_in {
897             #[cfg(any(
898                 bsd,
899                 target_os = "haiku",
900                 target_os = "hermit",
901                 target_os = "hurd"
902             ))]
903             sin_len: mem::size_of::<libc::sockaddr_in>() as u8,
904             sin_family: AddressFamily::Inet as sa_family_t,
905             sin_port: addr.port().to_be(), // network byte order
906             sin_addr: ipv4addr_to_libc(*addr.ip()),
907             ..unsafe { mem::zeroed() }
908         })
909     }
910 }
911 
912 #[cfg(feature = "net")]
913 impl From<SockaddrIn> for net::SocketAddrV4 {
from(addr: SockaddrIn) -> Self914     fn from(addr: SockaddrIn) -> Self {
915         net::SocketAddrV4::new(
916             net::Ipv4Addr::from(addr.0.sin_addr.s_addr.to_ne_bytes()),
917             u16::from_be(addr.0.sin_port),
918         )
919     }
920 }
921 
922 #[cfg(feature = "net")]
923 impl From<SockaddrIn> for libc::sockaddr_in {
from(sin: SockaddrIn) -> libc::sockaddr_in924     fn from(sin: SockaddrIn) -> libc::sockaddr_in {
925         sin.0
926     }
927 }
928 #[cfg(feature = "net")]
929 impl From<libc::sockaddr_in> for SockaddrIn {
from(sin: libc::sockaddr_in) -> SockaddrIn930     fn from(sin: libc::sockaddr_in) -> SockaddrIn {
931         SockaddrIn(sin)
932     }
933 }
934 
935 #[cfg(feature = "net")]
936 impl std::str::FromStr for SockaddrIn {
937     type Err = net::AddrParseError;
938 
from_str(s: &str) -> std::result::Result<Self, Self::Err>939     fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
940         net::SocketAddrV4::from_str(s).map(SockaddrIn::from)
941     }
942 }
943 
944 /// An IPv6 socket address
945 #[cfg(feature = "net")]
946 #[repr(transparent)]
947 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
948 pub struct SockaddrIn6(libc::sockaddr_in6);
949 
950 #[cfg(feature = "net")]
951 impl SockaddrIn6 {
952     /// Returns the flow information associated with this address.
flowinfo(&self) -> u32953     pub const fn flowinfo(&self) -> u32 {
954         self.0.sin6_flowinfo
955     }
956 
957     /// Returns the IP address associated with this socket address.
ip(&self) -> net::Ipv6Addr958     pub const fn ip(&self) -> net::Ipv6Addr {
959         let bytes = self.0.sin6_addr.s6_addr;
960         let (a, b, c, d, e, f, g, h) = (
961             ((bytes[0] as u16) << 8) | bytes[1] as u16,
962             ((bytes[2] as u16) << 8) | bytes[3] as u16,
963             ((bytes[4] as u16) << 8) | bytes[5] as u16,
964             ((bytes[6] as u16) << 8) | bytes[7] as u16,
965             ((bytes[8] as u16) << 8) | bytes[9] as u16,
966             ((bytes[10] as u16) << 8) | bytes[11] as u16,
967             ((bytes[12] as u16) << 8) | bytes[13] as u16,
968             ((bytes[14] as u16) << 8) | bytes[15] as u16,
969         );
970         Ipv6Addr::new(a, b, c, d, e, f, g, h)
971     }
972 
973     /// Returns the port number associated with this socket address, in native
974     /// endian.
port(&self) -> u16975     pub const fn port(&self) -> u16 {
976         u16::from_be(self.0.sin6_port)
977     }
978 
979     /// Returns the scope ID associated with this address.
scope_id(&self) -> u32980     pub const fn scope_id(&self) -> u32 {
981         self.0.sin6_scope_id
982     }
983 }
984 
985 #[cfg(feature = "net")]
986 impl From<SockaddrIn6> for libc::sockaddr_in6 {
from(sin6: SockaddrIn6) -> libc::sockaddr_in6987     fn from(sin6: SockaddrIn6) -> libc::sockaddr_in6 {
988         sin6.0
989     }
990 }
991 
992 #[cfg(feature = "net")]
993 impl From<libc::sockaddr_in6> for SockaddrIn6 {
from(sin6: libc::sockaddr_in6) -> SockaddrIn6994     fn from(sin6: libc::sockaddr_in6) -> SockaddrIn6 {
995         SockaddrIn6(sin6)
996     }
997 }
998 
999 #[cfg(feature = "net")]
1000 impl private::SockaddrLikePriv for SockaddrIn6 {}
1001 #[cfg(feature = "net")]
1002 impl SockaddrLike for SockaddrIn6 {
from_raw( addr: *const libc::sockaddr, len: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,1003     unsafe fn from_raw(
1004         addr: *const libc::sockaddr,
1005         len: Option<libc::socklen_t>,
1006     ) -> Option<Self>
1007     where
1008         Self: Sized,
1009     {
1010         if let Some(l) = len {
1011             if l != mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t {
1012                 return None;
1013             }
1014         }
1015         if unsafe { (*addr).sa_family as i32 != libc::AF_INET6 } {
1016             return None;
1017         }
1018         Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
1019     }
1020 }
1021 
1022 #[cfg(feature = "net")]
1023 impl AsRef<libc::sockaddr_in6> for SockaddrIn6 {
as_ref(&self) -> &libc::sockaddr_in61024     fn as_ref(&self) -> &libc::sockaddr_in6 {
1025         &self.0
1026     }
1027 }
1028 
1029 #[cfg(feature = "net")]
1030 impl fmt::Display for SockaddrIn6 {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1031     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1032         // These things are really hard to display properly.  Easier to let std
1033         // do it.
1034         let std = net::SocketAddrV6::new(
1035             self.ip(),
1036             self.port(),
1037             self.flowinfo(),
1038             self.scope_id(),
1039         );
1040         std.fmt(f)
1041     }
1042 }
1043 
1044 #[cfg(feature = "net")]
1045 impl From<net::SocketAddrV6> for SockaddrIn6 {
from(addr: net::SocketAddrV6) -> Self1046     fn from(addr: net::SocketAddrV6) -> Self {
1047         #[allow(clippy::needless_update)] // It isn't needless on Illumos
1048         Self(libc::sockaddr_in6 {
1049             #[cfg(any(
1050                 bsd,
1051                 target_os = "haiku",
1052                 target_os = "hermit",
1053                 target_os = "hurd"
1054             ))]
1055             sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8,
1056             sin6_family: AddressFamily::Inet6 as sa_family_t,
1057             sin6_port: addr.port().to_be(), // network byte order
1058             sin6_addr: ipv6addr_to_libc(addr.ip()),
1059             sin6_flowinfo: addr.flowinfo(), // host byte order
1060             sin6_scope_id: addr.scope_id(), // host byte order
1061             ..unsafe { mem::zeroed() }
1062         })
1063     }
1064 }
1065 
1066 #[cfg(feature = "net")]
1067 impl From<SockaddrIn6> for net::SocketAddrV6 {
from(addr: SockaddrIn6) -> Self1068     fn from(addr: SockaddrIn6) -> Self {
1069         net::SocketAddrV6::new(
1070             net::Ipv6Addr::from(addr.0.sin6_addr.s6_addr),
1071             u16::from_be(addr.0.sin6_port),
1072             addr.0.sin6_flowinfo,
1073             addr.0.sin6_scope_id,
1074         )
1075     }
1076 }
1077 
1078 #[cfg(feature = "net")]
1079 impl std::str::FromStr for SockaddrIn6 {
1080     type Err = net::AddrParseError;
1081 
from_str(s: &str) -> std::result::Result<Self, Self::Err>1082     fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
1083         net::SocketAddrV6::from_str(s).map(SockaddrIn6::from)
1084     }
1085 }
1086 
1087 /// A container for any sockaddr type
1088 ///
1089 /// Just like C's `sockaddr_storage`, this type is large enough to hold any type
1090 /// of sockaddr.  It can be used as an argument with functions like
1091 /// [`bind`](super::bind) and [`getsockname`](super::getsockname).  Though it is
1092 /// a union, it can be safely accessed through the `as_*` methods.
1093 ///
1094 /// # Example
1095 /// ```
1096 /// # use nix::sys::socket::*;
1097 /// # use std::str::FromStr;
1098 /// # use std::os::unix::io::AsRawFd;
1099 /// let localhost = SockaddrIn::from_str("127.0.0.1:8081").unwrap();
1100 /// let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(),
1101 ///     None).unwrap();
1102 /// bind(fd.as_raw_fd(), &localhost).expect("bind");
1103 /// let ss: SockaddrStorage = getsockname(fd.as_raw_fd()).expect("getsockname");
1104 /// assert_eq!(&localhost, ss.as_sockaddr_in().unwrap());
1105 /// ```
1106 #[derive(Clone, Copy, Eq)]
1107 #[repr(C)]
1108 pub union SockaddrStorage {
1109     #[cfg(linux_android)]
1110     alg: AlgAddr,
1111     #[cfg(all(
1112         feature = "net",
1113         not(any(target_os = "hurd", target_os = "redox"))
1114     ))]
1115     #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1116     dl: LinkAddr,
1117     #[cfg(linux_android)]
1118     nl: NetlinkAddr,
1119     #[cfg(all(feature = "ioctl", apple_targets))]
1120     #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
1121     sctl: SysControlAddr,
1122     #[cfg(feature = "net")]
1123     sin: SockaddrIn,
1124     #[cfg(feature = "net")]
1125     sin6: SockaddrIn6,
1126     ss: libc::sockaddr_storage,
1127     su: UnixAddr,
1128     #[cfg(any(linux_android, apple_targets))]
1129     vsock: VsockAddr,
1130 }
1131 impl private::SockaddrLikePriv for SockaddrStorage {}
1132 impl SockaddrLike for SockaddrStorage {
from_raw( addr: *const libc::sockaddr, l: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,1133     unsafe fn from_raw(
1134         addr: *const libc::sockaddr,
1135         l: Option<libc::socklen_t>,
1136     ) -> Option<Self>
1137     where
1138         Self: Sized,
1139     {
1140         if addr.is_null() {
1141             return None;
1142         }
1143         if let Some(len) = l {
1144             let ulen = len as usize;
1145             if ulen < offset_of!(libc::sockaddr, sa_data)
1146                 || ulen > mem::size_of::<libc::sockaddr_storage>()
1147             {
1148                 None
1149             } else {
1150                 let mut ss: libc::sockaddr_storage = unsafe { mem::zeroed() };
1151                 let ssp = &mut ss as *mut libc::sockaddr_storage as *mut u8;
1152                 unsafe { ptr::copy(addr as *const u8, ssp, len as usize) };
1153                 #[cfg(any(
1154                     linux_android,
1155                     target_os = "fuchsia",
1156                     solarish,
1157                 ))]
1158                 if i32::from(ss.ss_family) == libc::AF_UNIX {
1159                     // Safe because we UnixAddr is strictly smaller than
1160                     // SockaddrStorage, and we just initialized the structure.
1161                     unsafe {
1162                         (*(&mut ss as *mut libc::sockaddr_storage
1163                             as *mut UnixAddr))
1164                             .sun_len = len as u8;
1165                     }
1166                 }
1167                 Some(Self { ss })
1168             }
1169         } else {
1170             // If length is not available and addr is of a fixed-length type,
1171             // copy it.  If addr is of a variable length type and len is not
1172             // available, then there's nothing we can do.
1173             match unsafe { (*addr).sa_family as i32 } {
1174                 #[cfg(linux_android)]
1175                 libc::AF_ALG => unsafe {
1176                     AlgAddr::from_raw(addr, l).map(|alg| Self { alg })
1177                 },
1178                 #[cfg(feature = "net")]
1179                 libc::AF_INET => unsafe {
1180                     SockaddrIn::from_raw(addr, l).map(|sin| Self { sin })
1181                 },
1182                 #[cfg(feature = "net")]
1183                 libc::AF_INET6 => unsafe {
1184                     SockaddrIn6::from_raw(addr, l).map(|sin6| Self { sin6 })
1185                 },
1186                 #[cfg(any(bsd, solarish, target_os = "haiku"))]
1187                 #[cfg(feature = "net")]
1188                 libc::AF_LINK => unsafe {
1189                     LinkAddr::from_raw(addr, l).map(|dl| Self { dl })
1190                 },
1191                 #[cfg(linux_android)]
1192                 libc::AF_NETLINK => unsafe {
1193                     NetlinkAddr::from_raw(addr, l).map(|nl| Self { nl })
1194                 },
1195                 #[cfg(any(linux_android, target_os = "fuchsia"))]
1196                 #[cfg(feature = "net")]
1197                 libc::AF_PACKET => unsafe {
1198                     LinkAddr::from_raw(addr, l).map(|dl| Self { dl })
1199                 },
1200                 #[cfg(all(feature = "ioctl", apple_targets))]
1201                 libc::AF_SYSTEM => unsafe {
1202                     SysControlAddr::from_raw(addr, l).map(|sctl| Self { sctl })
1203                 },
1204                 #[cfg(any(linux_android, apple_targets))]
1205                 libc::AF_VSOCK => unsafe {
1206                     VsockAddr::from_raw(addr, l).map(|vsock| Self { vsock })
1207                 },
1208                 _ => None,
1209             }
1210         }
1211     }
1212 
1213     #[cfg(any(linux_android, target_os = "fuchsia", solarish))]
len(&self) -> libc::socklen_t1214     fn len(&self) -> libc::socklen_t {
1215         match self.as_unix_addr() {
1216             // The UnixAddr type knows its own length
1217             Some(ua) => ua.len(),
1218             // For all else, we're just a boring SockaddrStorage
1219             None => mem::size_of_val(self) as libc::socklen_t,
1220         }
1221     }
1222 
set_length( &mut self, new_length: usize, ) -> std::result::Result<(), SocketAddressLengthNotDynamic>1223     unsafe fn set_length(
1224         &mut self,
1225         new_length: usize,
1226     ) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
1227         match self.as_unix_addr_mut() {
1228             Some(addr) => unsafe { addr.set_length(new_length) },
1229             None => Err(SocketAddressLengthNotDynamic),
1230         }
1231     }
1232 }
1233 
1234 macro_rules! accessors {
1235     (
1236         $fname:ident,
1237         $fname_mut:ident,
1238         $sockty:ty,
1239         $family:expr,
1240         $libc_ty:ty,
1241         $field:ident) => {
1242         /// Safely and falliably downcast to an immutable reference
1243         pub fn $fname(&self) -> Option<&$sockty> {
1244             if self.family() == Some($family)
1245                 && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
1246             {
1247                 // Safe because family and len are validated
1248                 Some(unsafe { &self.$field })
1249             } else {
1250                 None
1251             }
1252         }
1253 
1254         /// Safely and falliably downcast to a mutable reference
1255         pub fn $fname_mut(&mut self) -> Option<&mut $sockty> {
1256             if self.family() == Some($family)
1257                 && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
1258             {
1259                 // Safe because family and len are validated
1260                 Some(unsafe { &mut self.$field })
1261             } else {
1262                 None
1263             }
1264         }
1265     };
1266 }
1267 
1268 impl SockaddrStorage {
1269     /// Downcast to an immutable `[UnixAddr]` reference.
as_unix_addr(&self) -> Option<&UnixAddr>1270     pub fn as_unix_addr(&self) -> Option<&UnixAddr> {
1271         cfg_if! {
1272             if #[cfg(any(linux_android,
1273                      target_os = "fuchsia",
1274                      solarish,
1275                 ))]
1276             {
1277                 let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
1278                 // Safe because UnixAddr is strictly smaller than
1279                 // sockaddr_storage, and we're fully initialized
1280                 let len = unsafe {
1281                     (*(p as *const UnixAddr )).sun_len as usize
1282                 };
1283             } else {
1284                 let len = self.len() as usize;
1285             }
1286         }
1287         // Sanity checks
1288         if self.family() != Some(AddressFamily::Unix)
1289             || len < offset_of!(libc::sockaddr_un, sun_path)
1290             || len > mem::size_of::<libc::sockaddr_un>()
1291         {
1292             None
1293         } else {
1294             Some(unsafe { &self.su })
1295         }
1296     }
1297 
1298     /// Downcast to a mutable `[UnixAddr]` reference.
as_unix_addr_mut(&mut self) -> Option<&mut UnixAddr>1299     pub fn as_unix_addr_mut(&mut self) -> Option<&mut UnixAddr> {
1300         cfg_if! {
1301             if #[cfg(any(linux_android,
1302                      target_os = "fuchsia",
1303                      solarish,
1304                 ))]
1305             {
1306                 let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
1307                 // Safe because UnixAddr is strictly smaller than
1308                 // sockaddr_storage, and we're fully initialized
1309                 let len = unsafe {
1310                     (*(p as *const UnixAddr )).sun_len as usize
1311                 };
1312             } else {
1313                 let len = self.len() as usize;
1314             }
1315         }
1316         // Sanity checks
1317         if self.family() != Some(AddressFamily::Unix)
1318             || len < offset_of!(libc::sockaddr_un, sun_path)
1319             || len > mem::size_of::<libc::sockaddr_un>()
1320         {
1321             None
1322         } else {
1323             Some(unsafe { &mut self.su })
1324         }
1325     }
1326 
1327     #[cfg(linux_android)]
1328     accessors! {as_alg_addr, as_alg_addr_mut, AlgAddr,
1329     AddressFamily::Alg, libc::sockaddr_alg, alg}
1330 
1331     #[cfg(any(linux_android, target_os = "fuchsia"))]
1332     #[cfg(feature = "net")]
1333     accessors! {
1334     as_link_addr, as_link_addr_mut, LinkAddr,
1335     AddressFamily::Packet, libc::sockaddr_ll, dl}
1336 
1337     #[cfg(any(bsd, solarish))]
1338     #[cfg(feature = "net")]
1339     accessors! {
1340     as_link_addr, as_link_addr_mut, LinkAddr,
1341     AddressFamily::Link, libc::sockaddr_dl, dl}
1342 
1343     #[cfg(feature = "net")]
1344     accessors! {
1345     as_sockaddr_in, as_sockaddr_in_mut, SockaddrIn,
1346     AddressFamily::Inet, libc::sockaddr_in, sin}
1347 
1348     #[cfg(feature = "net")]
1349     accessors! {
1350     as_sockaddr_in6, as_sockaddr_in6_mut, SockaddrIn6,
1351     AddressFamily::Inet6, libc::sockaddr_in6, sin6}
1352 
1353     #[cfg(linux_android)]
1354     accessors! {as_netlink_addr, as_netlink_addr_mut, NetlinkAddr,
1355     AddressFamily::Netlink, libc::sockaddr_nl, nl}
1356 
1357     #[cfg(all(feature = "ioctl", apple_targets))]
1358     #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
1359     accessors! {as_sys_control_addr, as_sys_control_addr_mut, SysControlAddr,
1360     AddressFamily::System, libc::sockaddr_ctl, sctl}
1361 
1362     #[cfg(any(linux_android, apple_targets))]
1363     accessors! {as_vsock_addr, as_vsock_addr_mut, VsockAddr,
1364     AddressFamily::Vsock, libc::sockaddr_vm, vsock}
1365 }
1366 
1367 impl fmt::Debug for SockaddrStorage {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1368     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1369         f.debug_struct("SockaddrStorage")
1370             // Safe because sockaddr_storage has the least specific
1371             // field types
1372             .field("ss", unsafe { &self.ss })
1373             .finish()
1374     }
1375 }
1376 
1377 impl fmt::Display for SockaddrStorage {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1378     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1379         unsafe {
1380             match self.ss.ss_family as i32 {
1381                 #[cfg(linux_android)]
1382                 libc::AF_ALG => self.alg.fmt(f),
1383                 #[cfg(feature = "net")]
1384                 libc::AF_INET => self.sin.fmt(f),
1385                 #[cfg(feature = "net")]
1386                 libc::AF_INET6 => self.sin6.fmt(f),
1387                 #[cfg(any(bsd, solarish))]
1388                 #[cfg(feature = "net")]
1389                 libc::AF_LINK => self.dl.fmt(f),
1390                 #[cfg(linux_android)]
1391                 libc::AF_NETLINK => self.nl.fmt(f),
1392                 #[cfg(any(linux_android, target_os = "fuchsia"))]
1393                 #[cfg(feature = "net")]
1394                 libc::AF_PACKET => self.dl.fmt(f),
1395                 #[cfg(apple_targets)]
1396                 #[cfg(feature = "ioctl")]
1397                 libc::AF_SYSTEM => self.sctl.fmt(f),
1398                 libc::AF_UNIX => self.su.fmt(f),
1399                 #[cfg(any(linux_android, apple_targets))]
1400                 libc::AF_VSOCK => self.vsock.fmt(f),
1401                 _ => "<Address family unspecified>".fmt(f),
1402             }
1403         }
1404     }
1405 }
1406 
1407 #[cfg(feature = "net")]
1408 impl From<net::SocketAddrV4> for SockaddrStorage {
from(s: net::SocketAddrV4) -> Self1409     fn from(s: net::SocketAddrV4) -> Self {
1410         unsafe {
1411             let mut ss: Self = mem::zeroed();
1412             ss.sin = SockaddrIn::from(s);
1413             ss
1414         }
1415     }
1416 }
1417 
1418 #[cfg(feature = "net")]
1419 impl From<net::SocketAddrV6> for SockaddrStorage {
from(s: net::SocketAddrV6) -> Self1420     fn from(s: net::SocketAddrV6) -> Self {
1421         unsafe {
1422             let mut ss: Self = mem::zeroed();
1423             ss.sin6 = SockaddrIn6::from(s);
1424             ss
1425         }
1426     }
1427 }
1428 
1429 #[cfg(feature = "net")]
1430 impl From<net::SocketAddr> for SockaddrStorage {
from(s: net::SocketAddr) -> Self1431     fn from(s: net::SocketAddr) -> Self {
1432         match s {
1433             net::SocketAddr::V4(sa4) => Self::from(sa4),
1434             net::SocketAddr::V6(sa6) => Self::from(sa6),
1435         }
1436     }
1437 }
1438 
1439 impl Hash for SockaddrStorage {
hash<H: Hasher>(&self, s: &mut H)1440     fn hash<H: Hasher>(&self, s: &mut H) {
1441         unsafe {
1442             match self.ss.ss_family as i32 {
1443                 #[cfg(linux_android)]
1444                 libc::AF_ALG => self.alg.hash(s),
1445                 #[cfg(feature = "net")]
1446                 libc::AF_INET => self.sin.hash(s),
1447                 #[cfg(feature = "net")]
1448                 libc::AF_INET6 => self.sin6.hash(s),
1449                 #[cfg(any(bsd, solarish))]
1450                 #[cfg(feature = "net")]
1451                 libc::AF_LINK => self.dl.hash(s),
1452                 #[cfg(linux_android)]
1453                 libc::AF_NETLINK => self.nl.hash(s),
1454                 #[cfg(any(linux_android, target_os = "fuchsia"))]
1455                 #[cfg(feature = "net")]
1456                 libc::AF_PACKET => self.dl.hash(s),
1457                 #[cfg(apple_targets)]
1458                 #[cfg(feature = "ioctl")]
1459                 libc::AF_SYSTEM => self.sctl.hash(s),
1460                 libc::AF_UNIX => self.su.hash(s),
1461                 #[cfg(any(linux_android, apple_targets))]
1462                 libc::AF_VSOCK => self.vsock.hash(s),
1463                 _ => self.ss.hash(s),
1464             }
1465         }
1466     }
1467 }
1468 
1469 impl PartialEq for SockaddrStorage {
eq(&self, other: &Self) -> bool1470     fn eq(&self, other: &Self) -> bool {
1471         unsafe {
1472             match (self.ss.ss_family as i32, other.ss.ss_family as i32) {
1473                 #[cfg(linux_android)]
1474                 (libc::AF_ALG, libc::AF_ALG) => self.alg == other.alg,
1475                 #[cfg(feature = "net")]
1476                 (libc::AF_INET, libc::AF_INET) => self.sin == other.sin,
1477                 #[cfg(feature = "net")]
1478                 (libc::AF_INET6, libc::AF_INET6) => self.sin6 == other.sin6,
1479                 #[cfg(any(bsd, solarish))]
1480                 #[cfg(feature = "net")]
1481                 (libc::AF_LINK, libc::AF_LINK) => self.dl == other.dl,
1482                 #[cfg(linux_android)]
1483                 (libc::AF_NETLINK, libc::AF_NETLINK) => self.nl == other.nl,
1484                 #[cfg(any(linux_android, target_os = "fuchsia"))]
1485                 #[cfg(feature = "net")]
1486                 (libc::AF_PACKET, libc::AF_PACKET) => self.dl == other.dl,
1487                 #[cfg(apple_targets)]
1488                 #[cfg(feature = "ioctl")]
1489                 (libc::AF_SYSTEM, libc::AF_SYSTEM) => self.sctl == other.sctl,
1490                 (libc::AF_UNIX, libc::AF_UNIX) => self.su == other.su,
1491                 #[cfg(any(linux_android, apple_targets))]
1492                 (libc::AF_VSOCK, libc::AF_VSOCK) => self.vsock == other.vsock,
1493                 _ => false,
1494             }
1495         }
1496     }
1497 }
1498 
1499 pub(super) mod private {
1500     pub trait SockaddrLikePriv {
1501         /// Returns a mutable raw pointer to the inner structure.
1502         ///
1503         /// # Safety
1504         ///
1505         /// This method is technically safe, but modifying the inner structure's
1506         /// `family` or `len` fields may result in violating Nix's invariants.
1507         /// It is best to use this method only with foreign functions that do
1508         /// not change the sockaddr type.
as_mut_ptr(&mut self) -> *mut libc::sockaddr1509         fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
1510             self as *mut Self as *mut libc::sockaddr
1511         }
1512     }
1513 }
1514 
1515 #[cfg(linux_android)]
1516 pub mod netlink {
1517     use super::*;
1518     use crate::sys::socket::addr::AddressFamily;
1519     use libc::{sa_family_t, sockaddr_nl};
1520     use std::{fmt, mem};
1521 
1522     /// Address for the Linux kernel user interface device.
1523     ///
1524     /// # References
1525     ///
1526     /// [netlink(7)](https://man7.org/linux/man-pages/man7/netlink.7.html)
1527     #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
1528     #[repr(transparent)]
1529     pub struct NetlinkAddr(pub(in super::super) sockaddr_nl);
1530 
1531     impl NetlinkAddr {
1532         /// Construct a new socket address from its port ID and multicast groups
1533         /// mask.
new(pid: u32, groups: u32) -> NetlinkAddr1534         pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
1535             let mut addr: sockaddr_nl = unsafe { mem::zeroed() };
1536             addr.nl_family = AddressFamily::Netlink as sa_family_t;
1537             addr.nl_pid = pid;
1538             addr.nl_groups = groups;
1539 
1540             NetlinkAddr(addr)
1541         }
1542 
1543         /// Return the socket's port ID.
pid(&self) -> u321544         pub const fn pid(&self) -> u32 {
1545             self.0.nl_pid
1546         }
1547 
1548         /// Return the socket's multicast groups mask
groups(&self) -> u321549         pub const fn groups(&self) -> u32 {
1550             self.0.nl_groups
1551         }
1552     }
1553 
1554     impl private::SockaddrLikePriv for NetlinkAddr {}
1555     impl SockaddrLike for NetlinkAddr {
from_raw( addr: *const libc::sockaddr, len: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,1556         unsafe fn from_raw(
1557             addr: *const libc::sockaddr,
1558             len: Option<libc::socklen_t>,
1559         ) -> Option<Self>
1560         where
1561             Self: Sized,
1562         {
1563             if let Some(l) = len {
1564                 if l != mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t {
1565                     return None;
1566                 }
1567             }
1568             if unsafe { (*addr).sa_family as i32 != libc::AF_NETLINK } {
1569                 return None;
1570             }
1571             Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
1572         }
1573     }
1574 
1575     impl AsRef<libc::sockaddr_nl> for NetlinkAddr {
as_ref(&self) -> &libc::sockaddr_nl1576         fn as_ref(&self) -> &libc::sockaddr_nl {
1577             &self.0
1578         }
1579     }
1580 
1581     impl fmt::Display for NetlinkAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1582         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1583             write!(f, "pid: {} groups: {}", self.pid(), self.groups())
1584         }
1585     }
1586 }
1587 
1588 #[cfg(linux_android)]
1589 pub mod alg {
1590     use super::*;
1591     use libc::{sockaddr_alg, AF_ALG};
1592     use std::ffi::CStr;
1593     use std::hash::{Hash, Hasher};
1594     use std::{fmt, mem, str};
1595 
1596     /// Socket address for the Linux kernel crypto API
1597     #[derive(Copy, Clone)]
1598     #[repr(transparent)]
1599     pub struct AlgAddr(pub(in super::super) sockaddr_alg);
1600 
1601     impl private::SockaddrLikePriv for AlgAddr {}
1602     impl SockaddrLike for AlgAddr {
from_raw( addr: *const libc::sockaddr, l: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,1603         unsafe fn from_raw(
1604             addr: *const libc::sockaddr,
1605             l: Option<libc::socklen_t>,
1606         ) -> Option<Self>
1607         where
1608             Self: Sized,
1609         {
1610             if let Some(l) = l {
1611                 if l != mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t
1612                 {
1613                     return None;
1614                 }
1615             }
1616             if unsafe { (*addr).sa_family as i32 != libc::AF_ALG } {
1617                 return None;
1618             }
1619             Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
1620         }
1621     }
1622 
1623     impl AsRef<libc::sockaddr_alg> for AlgAddr {
as_ref(&self) -> &libc::sockaddr_alg1624         fn as_ref(&self) -> &libc::sockaddr_alg {
1625             &self.0
1626         }
1627     }
1628 
1629     // , PartialEq, Eq, Debug, Hash
1630     impl PartialEq for AlgAddr {
eq(&self, other: &Self) -> bool1631         fn eq(&self, other: &Self) -> bool {
1632             let (inner, other) = (self.0, other.0);
1633             (
1634                 inner.salg_family,
1635                 &inner.salg_type[..],
1636                 inner.salg_feat,
1637                 inner.salg_mask,
1638                 &inner.salg_name[..],
1639             ) == (
1640                 other.salg_family,
1641                 &other.salg_type[..],
1642                 other.salg_feat,
1643                 other.salg_mask,
1644                 &other.salg_name[..],
1645             )
1646         }
1647     }
1648 
1649     impl Eq for AlgAddr {}
1650 
1651     impl Hash for AlgAddr {
hash<H: Hasher>(&self, s: &mut H)1652         fn hash<H: Hasher>(&self, s: &mut H) {
1653             let inner = self.0;
1654             (
1655                 inner.salg_family,
1656                 &inner.salg_type[..],
1657                 inner.salg_feat,
1658                 inner.salg_mask,
1659                 &inner.salg_name[..],
1660             )
1661                 .hash(s);
1662         }
1663     }
1664 
1665     impl AlgAddr {
1666         /// Construct an `AF_ALG` socket from its cipher name and type.
new(alg_type: &str, alg_name: &str) -> AlgAddr1667         pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
1668             let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
1669             addr.salg_family = AF_ALG as u16;
1670             addr.salg_type[..alg_type.len()]
1671                 .copy_from_slice(alg_type.to_string().as_bytes());
1672             addr.salg_name[..alg_name.len()]
1673                 .copy_from_slice(alg_name.to_string().as_bytes());
1674 
1675             AlgAddr(addr)
1676         }
1677 
1678         /// Return the socket's cipher type, for example `hash` or `aead`.
alg_type(&self) -> &CStr1679         pub fn alg_type(&self) -> &CStr {
1680             unsafe { CStr::from_ptr(self.0.salg_type.as_ptr().cast()) }
1681         }
1682 
1683         /// Return the socket's cipher name, for example `sha1`.
alg_name(&self) -> &CStr1684         pub fn alg_name(&self) -> &CStr {
1685             unsafe { CStr::from_ptr(self.0.salg_name.as_ptr().cast()) }
1686         }
1687     }
1688 
1689     impl fmt::Display for AlgAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1690         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1691             write!(
1692                 f,
1693                 "type: {} alg: {}",
1694                 self.alg_name().to_string_lossy(),
1695                 self.alg_type().to_string_lossy()
1696             )
1697         }
1698     }
1699 
1700     impl fmt::Debug for AlgAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1701         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1702             fmt::Display::fmt(self, f)
1703         }
1704     }
1705 }
1706 
1707 feature! {
1708 #![feature = "ioctl"]
1709 #[cfg(apple_targets)]
1710 pub mod sys_control {
1711     use crate::sys::socket::addr::AddressFamily;
1712     use libc::{self, c_uchar};
1713     use std::{fmt, mem, ptr};
1714     use std::os::unix::io::RawFd;
1715     use crate::{Errno, Result};
1716     use super::{private, SockaddrLike};
1717 
1718     // FIXME: Move type into `libc`
1719     #[repr(C)]
1720     #[derive(Clone, Copy)]
1721     #[allow(missing_debug_implementations)]
1722     pub struct ctl_ioc_info {
1723         pub ctl_id: u32,
1724         pub ctl_name: [c_uchar; MAX_KCTL_NAME],
1725     }
1726 
1727     const CTL_IOC_MAGIC: u8 = b'N';
1728     const CTL_IOC_INFO: u8 = 3;
1729     const MAX_KCTL_NAME: usize = 96;
1730 
1731     ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info);
1732 
1733     /// Apple system control socket
1734     ///
1735     /// # References
1736     ///
1737     /// <https://developer.apple.com/documentation/kernel/sockaddr_ctl>
1738     #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1739     #[repr(transparent)]
1740     pub struct SysControlAddr(pub(in super::super) libc::sockaddr_ctl);
1741 
1742     impl private::SockaddrLikePriv for SysControlAddr {}
1743     impl SockaddrLike for SysControlAddr {
1744         unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
1745             -> Option<Self> where Self: Sized
1746         {
1747             if let Some(l) = len {
1748                 if l != mem::size_of::<libc::sockaddr_ctl>() as libc::socklen_t {
1749                     return None;
1750                 }
1751             }
1752             if unsafe { (*addr).sa_family as i32 != libc::AF_SYSTEM } {
1753                 return None;
1754             }
1755             Some(Self(unsafe { ptr::read_unaligned(addr as *const _) } ))
1756         }
1757     }
1758 
1759     impl AsRef<libc::sockaddr_ctl> for SysControlAddr {
1760         fn as_ref(&self) -> &libc::sockaddr_ctl {
1761             &self.0
1762         }
1763     }
1764 
1765     impl SysControlAddr {
1766         /// Construct a new `SysControlAddr` from its kernel unique identifier
1767         /// and unit number.
1768         pub const fn new(id: u32, unit: u32) -> SysControlAddr {
1769             let addr = libc::sockaddr_ctl {
1770                 sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
1771                 sc_family: AddressFamily::System as c_uchar,
1772                 ss_sysaddr: libc::AF_SYS_CONTROL as u16,
1773                 sc_id: id,
1774                 sc_unit: unit,
1775                 sc_reserved: [0; 5]
1776             };
1777 
1778             SysControlAddr(addr)
1779         }
1780 
1781         /// Construct a new `SysControlAddr` from its human readable name and
1782         /// unit number.
1783         pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
1784             if name.len() > MAX_KCTL_NAME {
1785                 return Err(Errno::ENAMETOOLONG);
1786             }
1787 
1788             let mut ctl_name = [0; MAX_KCTL_NAME];
1789             ctl_name[..name.len()].clone_from_slice(name.as_bytes());
1790             let mut info = ctl_ioc_info { ctl_id: 0, ctl_name };
1791 
1792             unsafe { ctl_info(sockfd, &mut info)?; }
1793 
1794             Ok(SysControlAddr::new(info.ctl_id, unit))
1795         }
1796 
1797         /// Return the kernel unique identifier
1798         pub const fn id(&self) -> u32 {
1799             self.0.sc_id
1800         }
1801 
1802         /// Return the kernel controller private unit number.
1803         pub const fn unit(&self) -> u32 {
1804             self.0.sc_unit
1805         }
1806     }
1807 
1808     impl fmt::Display for SysControlAddr {
1809         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1810             fmt::Debug::fmt(self, f)
1811         }
1812     }
1813 }
1814 }
1815 
1816 #[cfg(any(linux_android, target_os = "fuchsia"))]
1817 mod datalink {
1818     feature! {
1819     #![feature = "net"]
1820     use super::{fmt, mem, private, ptr, SockaddrLike};
1821 
1822     /// Hardware Address
1823     #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1824     #[repr(transparent)]
1825     pub struct LinkAddr(pub(in super::super) libc::sockaddr_ll);
1826 
1827     impl LinkAddr {
1828         /// Physical-layer protocol
1829         pub fn protocol(&self) -> u16 {
1830             self.0.sll_protocol
1831         }
1832 
1833         /// Interface number
1834         pub fn ifindex(&self) -> usize {
1835             self.0.sll_ifindex as usize
1836         }
1837 
1838         /// ARP hardware type
1839         pub fn hatype(&self) -> u16 {
1840             self.0.sll_hatype
1841         }
1842 
1843         /// Packet type
1844         pub fn pkttype(&self) -> u8 {
1845             self.0.sll_pkttype
1846         }
1847 
1848         /// Length of MAC address
1849         pub fn halen(&self) -> usize {
1850             self.0.sll_halen as usize
1851         }
1852 
1853         /// Physical-layer address (MAC)
1854         // Returns an Option just for cross-platform compatibility
1855         pub fn addr(&self) -> Option<[u8; 6]> {
1856             Some([
1857                 self.0.sll_addr[0],
1858                 self.0.sll_addr[1],
1859                 self.0.sll_addr[2],
1860                 self.0.sll_addr[3],
1861                 self.0.sll_addr[4],
1862                 self.0.sll_addr[5],
1863             ])
1864         }
1865     }
1866 
1867     impl fmt::Display for LinkAddr {
1868         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1869             if let Some(addr) = self.addr() {
1870                 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1871                     addr[0],
1872                     addr[1],
1873                     addr[2],
1874                     addr[3],
1875                     addr[4],
1876                     addr[5])
1877             } else {
1878                 Ok(())
1879             }
1880         }
1881     }
1882     impl private::SockaddrLikePriv for LinkAddr {}
1883     impl SockaddrLike for LinkAddr {
1884         unsafe fn from_raw(addr: *const libc::sockaddr,
1885                            len: Option<libc::socklen_t>)
1886             -> Option<Self> where Self: Sized
1887         {
1888             if let Some(l) = len {
1889                 if l != mem::size_of::<libc::sockaddr_ll>() as libc::socklen_t {
1890                     return None;
1891                 }
1892             }
1893             if unsafe { (*addr).sa_family as i32 != libc::AF_PACKET } {
1894                 return None;
1895             }
1896             Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
1897         }
1898     }
1899 
1900     impl AsRef<libc::sockaddr_ll> for LinkAddr {
1901         fn as_ref(&self) -> &libc::sockaddr_ll {
1902             &self.0
1903         }
1904     }
1905 
1906     }
1907 }
1908 
1909 #[cfg(any(bsd, solarish, target_os = "haiku", target_os = "aix"))]
1910 mod datalink {
1911     feature! {
1912     #![feature = "net"]
1913     use super::{fmt, mem, private, ptr, SockaddrLike};
1914 
1915     /// Hardware Address
1916     #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1917     #[repr(transparent)]
1918     pub struct LinkAddr(pub(in super::super) libc::sockaddr_dl);
1919 
1920     impl LinkAddr {
1921         /// interface index, if != 0, system given index for interface
1922         #[cfg(not(target_os = "haiku"))]
1923         pub fn ifindex(&self) -> usize {
1924             self.0.sdl_index as usize
1925         }
1926 
1927         /// Datalink type
1928         #[cfg(not(target_os = "haiku"))]
1929         pub fn datalink_type(&self) -> u8 {
1930             self.0.sdl_type
1931         }
1932 
1933         /// MAC address start position
1934         pub fn nlen(&self) -> usize {
1935             self.0.sdl_nlen as usize
1936         }
1937 
1938         /// link level address length
1939         pub fn alen(&self) -> usize {
1940             self.0.sdl_alen as usize
1941         }
1942 
1943         /// link layer selector length
1944         #[cfg(not(target_os = "haiku"))]
1945         pub fn slen(&self) -> usize {
1946             self.0.sdl_slen as usize
1947         }
1948 
1949         /// if link level address length == 0,
1950         /// or `sdl_data` not be larger.
1951         pub fn is_empty(&self) -> bool {
1952             let nlen = self.nlen();
1953             let alen = self.alen();
1954             let data_len = self.0.sdl_data.len();
1955 
1956             alen == 0 || nlen + alen >= data_len
1957         }
1958 
1959         /// Physical-layer address (MAC)
1960         // The cast is not unnecessary on all platforms.
1961         #[allow(clippy::unnecessary_cast)]
1962         pub fn addr(&self) -> Option<[u8; 6]> {
1963             let nlen = self.nlen();
1964             let data = self.0.sdl_data;
1965 
1966             if self.is_empty() {
1967                 None
1968             } else {
1969                 Some([
1970                     data[nlen] as u8,
1971                     data[nlen + 1] as u8,
1972                     data[nlen + 2] as u8,
1973                     data[nlen + 3] as u8,
1974                     data[nlen + 4] as u8,
1975                     data[nlen + 5] as u8,
1976                 ])
1977             }
1978         }
1979     }
1980 
1981     impl fmt::Display for LinkAddr {
1982         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1983             if let Some(addr) = self.addr() {
1984                 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1985                     addr[0],
1986                     addr[1],
1987                     addr[2],
1988                     addr[3],
1989                     addr[4],
1990                     addr[5])
1991             } else {
1992                 Ok(())
1993             }
1994         }
1995     }
1996     impl private::SockaddrLikePriv for LinkAddr {}
1997     impl SockaddrLike for LinkAddr {
1998         unsafe fn from_raw(addr: *const libc::sockaddr,
1999                            len: Option<libc::socklen_t>)
2000             -> Option<Self> where Self: Sized
2001         {
2002             if let Some(l) = len {
2003                 if l != mem::size_of::<libc::sockaddr_dl>() as libc::socklen_t {
2004                     return None;
2005                 }
2006             }
2007             if unsafe { (*addr).sa_family as i32 != libc::AF_LINK } {
2008                 return None;
2009             }
2010             Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
2011         }
2012     }
2013 
2014     impl AsRef<libc::sockaddr_dl> for LinkAddr {
2015         fn as_ref(&self) -> &libc::sockaddr_dl {
2016             &self.0
2017         }
2018     }
2019     }
2020 }
2021 
2022 #[cfg(any(linux_android, apple_targets))]
2023 pub mod vsock {
2024     use super::*;
2025     use crate::sys::socket::addr::AddressFamily;
2026     use libc::{sa_family_t, sockaddr_vm};
2027     use std::hash::{Hash, Hasher};
2028     use std::{fmt, mem};
2029 
2030     /// Socket address for VMWare VSockets protocol
2031     ///
2032     /// # References
2033     ///
2034     /// [vsock(7)](https://man7.org/linux/man-pages/man7/vsock.7.html)
2035     #[derive(Copy, Clone)]
2036     #[repr(transparent)]
2037     pub struct VsockAddr(pub(in super::super) sockaddr_vm);
2038 
2039     impl private::SockaddrLikePriv for VsockAddr {}
2040     impl SockaddrLike for VsockAddr {
from_raw( addr: *const libc::sockaddr, len: Option<libc::socklen_t>, ) -> Option<Self> where Self: Sized,2041         unsafe fn from_raw(
2042             addr: *const libc::sockaddr,
2043             len: Option<libc::socklen_t>,
2044         ) -> Option<Self>
2045         where
2046             Self: Sized,
2047         {
2048             if let Some(l) = len {
2049                 if l != mem::size_of::<libc::sockaddr_vm>() as libc::socklen_t {
2050                     return None;
2051                 }
2052             }
2053             if unsafe { (*addr).sa_family as i32 != libc::AF_VSOCK } {
2054                 return None;
2055             }
2056             unsafe { Some(Self(ptr::read_unaligned(addr as *const _))) }
2057         }
2058     }
2059 
2060     impl AsRef<libc::sockaddr_vm> for VsockAddr {
as_ref(&self) -> &libc::sockaddr_vm2061         fn as_ref(&self) -> &libc::sockaddr_vm {
2062             &self.0
2063         }
2064     }
2065 
2066     impl PartialEq for VsockAddr {
2067         #[cfg(linux_android)]
eq(&self, other: &Self) -> bool2068         fn eq(&self, other: &Self) -> bool {
2069             let (inner, other) = (self.0, other.0);
2070             (inner.svm_family, inner.svm_cid, inner.svm_port)
2071                 == (other.svm_family, other.svm_cid, other.svm_port)
2072         }
2073         #[cfg(apple_targets)]
eq(&self, other: &Self) -> bool2074         fn eq(&self, other: &Self) -> bool {
2075             let (inner, other) = (self.0, other.0);
2076             (
2077                 inner.svm_family,
2078                 inner.svm_cid,
2079                 inner.svm_port,
2080                 inner.svm_len,
2081             ) == (
2082                 other.svm_family,
2083                 other.svm_cid,
2084                 other.svm_port,
2085                 inner.svm_len,
2086             )
2087         }
2088     }
2089 
2090     impl Eq for VsockAddr {}
2091 
2092     impl Hash for VsockAddr {
2093         #[cfg(linux_android)]
hash<H: Hasher>(&self, s: &mut H)2094         fn hash<H: Hasher>(&self, s: &mut H) {
2095             let inner = self.0;
2096             (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
2097         }
2098         #[cfg(apple_targets)]
hash<H: Hasher>(&self, s: &mut H)2099         fn hash<H: Hasher>(&self, s: &mut H) {
2100             let inner = self.0;
2101             (
2102                 inner.svm_family,
2103                 inner.svm_cid,
2104                 inner.svm_port,
2105                 inner.svm_len,
2106             )
2107                 .hash(s);
2108         }
2109     }
2110 
2111     /// VSOCK Address
2112     ///
2113     /// The address for AF_VSOCK socket is defined as a combination of a
2114     /// 32-bit Context Identifier (CID) and a 32-bit port number.
2115     impl VsockAddr {
2116         /// Construct a `VsockAddr` from its raw fields.
new(cid: u32, port: u32) -> VsockAddr2117         pub fn new(cid: u32, port: u32) -> VsockAddr {
2118             let mut addr: sockaddr_vm = unsafe { mem::zeroed() };
2119             addr.svm_family = AddressFamily::Vsock as sa_family_t;
2120             addr.svm_cid = cid;
2121             addr.svm_port = port;
2122 
2123             #[cfg(apple_targets)]
2124             {
2125                 addr.svm_len = std::mem::size_of::<sockaddr_vm>() as u8;
2126             }
2127             VsockAddr(addr)
2128         }
2129 
2130         /// Context Identifier (CID)
cid(&self) -> u322131         pub fn cid(&self) -> u32 {
2132             self.0.svm_cid
2133         }
2134 
2135         /// Port number
port(&self) -> u322136         pub fn port(&self) -> u32 {
2137             self.0.svm_port
2138         }
2139     }
2140 
2141     impl fmt::Display for VsockAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result2142         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2143             write!(f, "cid: {} port: {}", self.cid(), self.port())
2144         }
2145     }
2146 
2147     impl fmt::Debug for VsockAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result2148         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2149             fmt::Display::fmt(self, f)
2150         }
2151     }
2152 }
2153 
2154 #[cfg(test)]
2155 mod tests {
2156     use super::*;
2157 
2158     mod types {
2159         use super::*;
2160 
2161         #[test]
test_ipv4addr_to_libc()2162         fn test_ipv4addr_to_libc() {
2163             let s = std::net::Ipv4Addr::new(1, 2, 3, 4);
2164             let l = ipv4addr_to_libc(s);
2165             assert_eq!(l.s_addr, u32::to_be(0x01020304));
2166         }
2167 
2168         #[test]
test_ipv6addr_to_libc()2169         fn test_ipv6addr_to_libc() {
2170             let s = std::net::Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8);
2171             let l = ipv6addr_to_libc(&s);
2172             assert_eq!(
2173                 l.s6_addr,
2174                 [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8]
2175             );
2176         }
2177     }
2178 
2179     #[cfg(not(any(target_os = "hurd", target_os = "redox")))]
2180     #[allow(clippy::cast_ptr_alignment)]
2181     mod link {
2182         #[cfg(any(apple_targets, solarish))]
2183         use super::super::super::socklen_t;
2184         use super::*;
2185 
2186         /// Don't panic when trying to display an empty datalink address
2187         #[cfg(bsd)]
2188         #[test]
test_datalink_display()2189         fn test_datalink_display() {
2190             use super::super::LinkAddr;
2191             use std::mem;
2192 
2193             let la = LinkAddr(libc::sockaddr_dl {
2194                 sdl_len: 56,
2195                 sdl_family: 18,
2196                 sdl_index: 5,
2197                 sdl_type: 24,
2198                 sdl_nlen: 3,
2199                 sdl_alen: 0,
2200                 sdl_slen: 0,
2201                 ..unsafe { mem::zeroed() }
2202             });
2203             format!("{la}");
2204         }
2205 
2206         #[cfg(all(
2207             any(linux_android, target_os = "fuchsia"),
2208             target_endian = "little"
2209         ))]
2210         #[test]
linux_loopback()2211         fn linux_loopback() {
2212             #[repr(align(2))]
2213             struct Raw([u8; 20]);
2214 
2215             let bytes = Raw([
2216                 17u8, 0, 0, 0, 1, 0, 0, 0, 4, 3, 0, 6, 1, 2, 3, 4, 5, 6, 0, 0,
2217             ]);
2218             let sa = bytes.0.as_ptr().cast();
2219             let len = None;
2220             let sock_addr =
2221                 unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
2222             assert_eq!(sock_addr.family(), Some(AddressFamily::Packet));
2223             match sock_addr.as_link_addr() {
2224                 Some(dl) => assert_eq!(dl.addr(), Some([1, 2, 3, 4, 5, 6])),
2225                 None => panic!("Can't unwrap sockaddr storage"),
2226             }
2227         }
2228 
2229         #[cfg(apple_targets)]
2230         #[test]
macos_loopback()2231         fn macos_loopback() {
2232             let bytes =
2233                 [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
2234             let sa = bytes.as_ptr().cast();
2235             let len = Some(bytes.len() as socklen_t);
2236             let sock_addr =
2237                 unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
2238             assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
2239             match sock_addr.as_link_addr() {
2240                 Some(dl) => {
2241                     assert!(dl.addr().is_none());
2242                 }
2243                 None => panic!("Can't unwrap sockaddr storage"),
2244             }
2245         }
2246 
2247         #[cfg(apple_targets)]
2248         #[test]
macos_tap()2249         fn macos_tap() {
2250             let bytes = [
2251                 20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35,
2252                 76, -80,
2253             ];
2254             let ptr = bytes.as_ptr();
2255             let sa = ptr as *const libc::sockaddr;
2256             let len = Some(bytes.len() as socklen_t);
2257 
2258             let sock_addr =
2259                 unsafe { SockaddrStorage::from_raw(sa, len).unwrap() };
2260             assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
2261             match sock_addr.as_link_addr() {
2262                 Some(dl) => {
2263                     assert_eq!(dl.addr(), Some([24u8, 101, 144, 221, 76, 176]))
2264                 }
2265                 None => panic!("Can't unwrap sockaddr storage"),
2266             }
2267         }
2268 
2269         #[cfg(solarish)]
2270         #[test]
solarish_tap()2271         fn solarish_tap() {
2272             let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176];
2273             let ptr = bytes.as_ptr();
2274             let sa = ptr as *const libc::sockaddr;
2275             let len = Some(bytes.len() as socklen_t);
2276             let _sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) };
2277 
2278             assert!(_sock_addr.is_some());
2279 
2280             let sock_addr = _sock_addr.unwrap();
2281 
2282             assert_eq!(sock_addr.family().unwrap(), AddressFamily::Link);
2283 
2284             assert_eq!(
2285                 sock_addr.as_link_addr().unwrap().addr(),
2286                 Some([24u8, 101, 144, 221, 76, 176])
2287             );
2288         }
2289 
2290         #[test]
size()2291         fn size() {
2292             #[cfg(any(bsd, target_os = "aix", solarish, target_os = "haiku"))]
2293             let l = mem::size_of::<libc::sockaddr_dl>();
2294             #[cfg(any(linux_android, target_os = "fuchsia"))]
2295             let l = mem::size_of::<libc::sockaddr_ll>();
2296             assert_eq!(LinkAddr::size() as usize, l);
2297         }
2298     }
2299 
2300     mod sockaddr_in {
2301         use super::*;
2302         use std::str::FromStr;
2303 
2304         #[test]
display()2305         fn display() {
2306             let s = "127.0.0.1:8080";
2307             let addr = SockaddrIn::from_str(s).unwrap();
2308             assert_eq!(s, format!("{addr}"));
2309         }
2310 
2311         #[test]
size()2312         fn size() {
2313             assert_eq!(
2314                 mem::size_of::<libc::sockaddr_in>(),
2315                 SockaddrIn::size() as usize
2316             );
2317         }
2318 
2319         #[test]
ip()2320         fn ip() {
2321             let s = "127.0.0.1:8082";
2322             let ip = SockaddrIn::from_str(s).unwrap().ip();
2323             assert_eq!("127.0.0.1", format!("{ip}"));
2324         }
2325     }
2326 
2327     mod sockaddr_in6 {
2328         use super::*;
2329         use std::str::FromStr;
2330 
2331         #[test]
display()2332         fn display() {
2333             let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
2334             let addr = SockaddrIn6::from_str(s).unwrap();
2335             assert_eq!(s, format!("{addr}"));
2336         }
2337 
2338         #[test]
size()2339         fn size() {
2340             assert_eq!(
2341                 mem::size_of::<libc::sockaddr_in6>(),
2342                 SockaddrIn6::size() as usize
2343             );
2344         }
2345 
2346         #[test]
ip()2347         fn ip() {
2348             let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
2349             let ip = SockaddrIn6::from_str(s).unwrap().ip();
2350             assert_eq!("1234:5678:90ab:cdef::1111:2222", format!("{ip}"));
2351         }
2352 
2353         #[test]
2354         // Ensure that we can convert to-and-from std::net variants without change.
to_and_from()2355         fn to_and_from() {
2356             let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
2357             let mut nix_sin6 = SockaddrIn6::from_str(s).unwrap();
2358             nix_sin6.0.sin6_flowinfo = 0x12345678;
2359             nix_sin6.0.sin6_scope_id = 0x9abcdef0;
2360 
2361             let std_sin6: std::net::SocketAddrV6 = nix_sin6.into();
2362             assert_eq!(nix_sin6, std_sin6.into());
2363         }
2364     }
2365 
2366     mod sockaddr_storage {
2367         use super::*;
2368 
2369         #[test]
from_sockaddr_un_named()2370         fn from_sockaddr_un_named() {
2371             let ua = UnixAddr::new("/var/run/mysock").unwrap();
2372             let ptr = ua.as_ptr().cast();
2373             let ss = unsafe { SockaddrStorage::from_raw(ptr, Some(ua.len())) }
2374                 .unwrap();
2375             assert_eq!(ss.len(), ua.len());
2376         }
2377 
2378         #[cfg(linux_android)]
2379         #[test]
from_sockaddr_un_abstract_named()2380         fn from_sockaddr_un_abstract_named() {
2381             let name = String::from("nix\0abstract\0test");
2382             let ua = UnixAddr::new_abstract(name.as_bytes()).unwrap();
2383             let ptr = ua.as_ptr().cast();
2384             let ss = unsafe { SockaddrStorage::from_raw(ptr, Some(ua.len())) }
2385                 .unwrap();
2386             assert_eq!(ss.len(), ua.len());
2387         }
2388 
2389         #[cfg(linux_android)]
2390         #[test]
from_sockaddr_un_abstract_unnamed()2391         fn from_sockaddr_un_abstract_unnamed() {
2392             let ua = UnixAddr::new_unnamed();
2393             let ptr = ua.as_ptr().cast();
2394             let ss = unsafe { SockaddrStorage::from_raw(ptr, Some(ua.len())) }
2395                 .unwrap();
2396             assert_eq!(ss.len(), ua.len());
2397         }
2398     }
2399 
2400     mod unixaddr {
2401         use super::*;
2402 
2403         #[cfg(linux_android)]
2404         #[test]
abstract_sun_path()2405         fn abstract_sun_path() {
2406             let name = String::from("nix\0abstract\0test");
2407             let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
2408 
2409             let sun_path1 =
2410                 unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] };
2411             let sun_path2 = [
2412                 0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0,
2413                 116, 101, 115, 116,
2414             ];
2415             assert_eq!(sun_path1, sun_path2);
2416         }
2417 
2418         #[test]
size()2419         fn size() {
2420             assert_eq!(
2421                 mem::size_of::<libc::sockaddr_un>(),
2422                 UnixAddr::size() as usize
2423             );
2424         }
2425     }
2426 }
2427