nix/sys/socket/
addr.rs

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")]
10pub use self::datalink::LinkAddr;
11#[cfg(any(linux_android, apple_targets))]
12pub use self::vsock::VsockAddr;
13use super::sa_family_t;
14use crate::errno::Errno;
15#[cfg(linux_android)]
16use crate::sys::socket::addr::alg::AlgAddr;
17#[cfg(linux_android)]
18use crate::sys::socket::addr::netlink::NetlinkAddr;
19#[cfg(all(feature = "ioctl", apple_targets))]
20use crate::sys::socket::addr::sys_control::SysControlAddr;
21use crate::{NixPath, Result};
22use cfg_if::cfg_if;
23use memoffset::offset_of;
24use std::convert::TryInto;
25use std::ffi::OsStr;
26use std::hash::{Hash, Hasher};
27use std::net::{Ipv4Addr, Ipv6Addr};
28use std::os::unix::ffi::OsStrExt;
29use std::path::Path;
30use std::{fmt, mem, net, ptr, slice};
31
32/// Convert a std::net::Ipv4Addr into the libc form.
33#[cfg(feature = "net")]
34pub(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")]
42pub(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)]
58pub 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
251impl 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.
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)]
282pub 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)]
299enum UnixAddrKind<'a> {
300    Pathname(&'a Path),
301    Unnamed,
302    #[cfg(linux_android)]
303    Abstract(&'a [u8]),
304}
305impl<'a> UnixAddrKind<'a> {
306    /// Safety: sun & sun_len must be valid
307    #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms
308    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
345impl UnixAddr {
346    /// Create a new sockaddr_un representing a filesystem path.
347    #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms
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
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)]
417    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.
440    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
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.
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)]
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]
487    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]
493    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]
498    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]
503    pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr_un {
504        &mut self.sun
505    }
506
507    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
523impl private::SockaddrLikePriv for UnixAddr {}
524impl SockaddrLike for UnixAddr {
525    #[cfg(any(
526        linux_android,
527        target_os = "fuchsia",
528        solarish,
529        target_os = "redox"
530    ))]
531    fn len(&self) -> libc::socklen_t {
532        self.sun_len.into()
533    }
534
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
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
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
597impl AsRef<libc::sockaddr_un> for UnixAddr {
598    fn as_ref(&self) -> &libc::sockaddr_un {
599        &self.sun
600    }
601}
602
603#[cfg(linux_android)]
604fn 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
615impl fmt::Display for UnixAddr {
616    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
626impl PartialEq for UnixAddr {
627    fn eq(&self, other: &UnixAddr) -> bool {
628        self.kind() == other.kind()
629    }
630}
631
632impl Eq for UnixAddr {}
633
634impl Hash for UnixAddr {
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)]
645pub trait SockaddrLike: private::SockaddrLikePriv {
646    /// Returns a raw pointer to the inner structure.  Useful for FFI.
647    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`.
672    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    /// ```
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
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)]
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)]
762pub struct SocketAddressLengthNotDynamic;
763impl fmt::Display for SocketAddressLengthNotDynamic {
764    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}
768impl std::error::Error for SocketAddressLengthNotDynamic {}
769
770impl private::SockaddrLikePriv for () {
771    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
780impl SockaddrLike for () {
781    fn as_ptr(&self) -> *const libc::sockaddr {
782        ptr::null()
783    }
784
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
795    fn family(&self) -> Option<AddressFamily> {
796        None
797    }
798
799    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)]
808pub struct SockaddrIn(libc::sockaddr_in);
809
810#[cfg(feature = "net")]
811impl SockaddrIn {
812    /// Returns the IP address associated with this socket address, in native
813    /// endian.
814    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.
821    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.
841    pub const fn port(&self) -> u16 {
842        u16::from_be(self.0.sin_port)
843    }
844}
845
846#[cfg(feature = "net")]
847impl private::SockaddrLikePriv for SockaddrIn {}
848#[cfg(feature = "net")]
849impl SockaddrLike for SockaddrIn {
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")]
870impl AsRef<libc::sockaddr_in> for SockaddrIn {
871    fn as_ref(&self) -> &libc::sockaddr_in {
872        &self.0
873    }
874}
875
876#[cfg(feature = "net")]
877impl fmt::Display for SockaddrIn {
878    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")]
894impl From<net::SocketAddrV4> for SockaddrIn {
895    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")]
913impl From<SockaddrIn> for net::SocketAddrV4 {
914    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")]
923impl From<SockaddrIn> for libc::sockaddr_in {
924    fn from(sin: SockaddrIn) -> libc::sockaddr_in {
925        sin.0
926    }
927}
928#[cfg(feature = "net")]
929impl From<libc::sockaddr_in> for SockaddrIn {
930    fn from(sin: libc::sockaddr_in) -> SockaddrIn {
931        SockaddrIn(sin)
932    }
933}
934
935#[cfg(feature = "net")]
936impl std::str::FromStr for SockaddrIn {
937    type Err = net::AddrParseError;
938
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)]
948pub struct SockaddrIn6(libc::sockaddr_in6);
949
950#[cfg(feature = "net")]
951impl SockaddrIn6 {
952    /// Returns the flow information associated with this address.
953    pub const fn flowinfo(&self) -> u32 {
954        self.0.sin6_flowinfo
955    }
956
957    /// Returns the IP address associated with this socket address.
958    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.
975    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.
980    pub const fn scope_id(&self) -> u32 {
981        self.0.sin6_scope_id
982    }
983}
984
985#[cfg(feature = "net")]
986impl From<SockaddrIn6> for libc::sockaddr_in6 {
987    fn from(sin6: SockaddrIn6) -> libc::sockaddr_in6 {
988        sin6.0
989    }
990}
991
992#[cfg(feature = "net")]
993impl From<libc::sockaddr_in6> for SockaddrIn6 {
994    fn from(sin6: libc::sockaddr_in6) -> SockaddrIn6 {
995        SockaddrIn6(sin6)
996    }
997}
998
999#[cfg(feature = "net")]
1000impl private::SockaddrLikePriv for SockaddrIn6 {}
1001#[cfg(feature = "net")]
1002impl SockaddrLike for SockaddrIn6 {
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")]
1023impl AsRef<libc::sockaddr_in6> for SockaddrIn6 {
1024    fn as_ref(&self) -> &libc::sockaddr_in6 {
1025        &self.0
1026    }
1027}
1028
1029#[cfg(feature = "net")]
1030impl fmt::Display for SockaddrIn6 {
1031    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")]
1045impl From<net::SocketAddrV6> for SockaddrIn6 {
1046    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")]
1067impl From<SockaddrIn6> for net::SocketAddrV6 {
1068    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")]
1079impl std::str::FromStr for SockaddrIn6 {
1080    type Err = net::AddrParseError;
1081
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)]
1108pub 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}
1131impl private::SockaddrLikePriv for SockaddrStorage {}
1132impl SockaddrLike for SockaddrStorage {
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))]
1214    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
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
1234macro_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
1268impl SockaddrStorage {
1269    /// Downcast to an immutable `[UnixAddr]` reference.
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.
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
1367impl fmt::Debug for SockaddrStorage {
1368    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
1377impl fmt::Display for SockaddrStorage {
1378    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")]
1408impl From<net::SocketAddrV4> for SockaddrStorage {
1409    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")]
1419impl From<net::SocketAddrV6> for SockaddrStorage {
1420    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")]
1430impl From<net::SocketAddr> for SockaddrStorage {
1431    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
1439impl Hash for SockaddrStorage {
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
1469impl PartialEq for SockaddrStorage {
1470    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
1499pub(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.
1509        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)]
1516pub 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.
1534        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.
1544        pub const fn pid(&self) -> u32 {
1545            self.0.nl_pid
1546        }
1547
1548        /// Return the socket's multicast groups mask
1549        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 {
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 {
1576        fn as_ref(&self) -> &libc::sockaddr_nl {
1577            &self.0
1578        }
1579    }
1580
1581    impl fmt::Display for NetlinkAddr {
1582        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)]
1589pub 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 {
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 {
1624        fn as_ref(&self) -> &libc::sockaddr_alg {
1625            &self.0
1626        }
1627    }
1628
1629    // , PartialEq, Eq, Debug, Hash
1630    impl PartialEq for AlgAddr {
1631        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 {
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.
1667        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`.
1679        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`.
1684        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 {
1690        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 {
1701        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1702            fmt::Display::fmt(self, f)
1703        }
1704    }
1705}
1706
1707feature! {
1708#![feature = "ioctl"]
1709#[cfg(apple_targets)]
1710pub 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"))]
1817mod 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"))]
1910mod 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))]
2023pub 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 {
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 {
2061        fn as_ref(&self) -> &libc::sockaddr_vm {
2062            &self.0
2063        }
2064    }
2065
2066    impl PartialEq for VsockAddr {
2067        #[cfg(linux_android)]
2068        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)]
2074        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)]
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)]
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.
2117        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)
2131        pub fn cid(&self) -> u32 {
2132            self.0.svm_cid
2133        }
2134
2135        /// Port number
2136        pub fn port(&self) -> u32 {
2137            self.0.svm_port
2138        }
2139    }
2140
2141    impl fmt::Display for VsockAddr {
2142        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 {
2148        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2149            fmt::Display::fmt(self, f)
2150        }
2151    }
2152}
2153
2154#[cfg(test)]
2155mod tests {
2156    use super::*;
2157
2158    mod types {
2159        use super::*;
2160
2161        #[test]
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]
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]
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]
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]
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]
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]
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]
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]
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]
2312        fn size() {
2313            assert_eq!(
2314                mem::size_of::<libc::sockaddr_in>(),
2315                SockaddrIn::size() as usize
2316            );
2317        }
2318
2319        #[test]
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]
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]
2339        fn size() {
2340            assert_eq!(
2341                mem::size_of::<libc::sockaddr_in6>(),
2342                SockaddrIn6::size() as usize
2343            );
2344        }
2345
2346        #[test]
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.
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]
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]
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]
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]
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]
2419        fn size() {
2420            assert_eq!(
2421                mem::size_of::<libc::sockaddr_un>(),
2422                UnixAddr::size() as usize
2423            );
2424        }
2425    }
2426}