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