13da5c369Sopenharmony_ci#[cfg(any(
23da5c369Sopenharmony_ci    target_os = "android",
33da5c369Sopenharmony_ci    target_os = "dragonfly",
43da5c369Sopenharmony_ci    target_os = "freebsd",
53da5c369Sopenharmony_ci    target_os = "ios",
63da5c369Sopenharmony_ci    target_os = "linux",
73da5c369Sopenharmony_ci    target_os = "macos",
83da5c369Sopenharmony_ci    target_os = "illumos",
93da5c369Sopenharmony_ci    target_os = "netbsd",
103da5c369Sopenharmony_ci    target_os = "openbsd",
113da5c369Sopenharmony_ci    target_os = "haiku",
123da5c369Sopenharmony_ci    target_os = "fuchsia"
133da5c369Sopenharmony_ci))]
143da5c369Sopenharmony_ci#[cfg(feature = "net")]
153da5c369Sopenharmony_cipub use self::datalink::LinkAddr;
163da5c369Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
173da5c369Sopenharmony_cipub use self::vsock::VsockAddr;
183da5c369Sopenharmony_ciuse super::sa_family_t;
193da5c369Sopenharmony_ciuse crate::errno::Errno;
203da5c369Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
213da5c369Sopenharmony_ciuse crate::sys::socket::addr::alg::AlgAddr;
223da5c369Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
233da5c369Sopenharmony_ciuse crate::sys::socket::addr::netlink::NetlinkAddr;
243da5c369Sopenharmony_ci#[cfg(all(
253da5c369Sopenharmony_ci    feature = "ioctl",
263da5c369Sopenharmony_ci    any(target_os = "ios", target_os = "macos")
273da5c369Sopenharmony_ci))]
283da5c369Sopenharmony_ciuse crate::sys::socket::addr::sys_control::SysControlAddr;
293da5c369Sopenharmony_ciuse crate::{NixPath, Result};
303da5c369Sopenharmony_ciuse cfg_if::cfg_if;
313da5c369Sopenharmony_ciuse memoffset::offset_of;
323da5c369Sopenharmony_ciuse std::convert::TryInto;
333da5c369Sopenharmony_ciuse std::ffi::OsStr;
343da5c369Sopenharmony_ciuse std::hash::{Hash, Hasher};
353da5c369Sopenharmony_ciuse std::os::unix::ffi::OsStrExt;
363da5c369Sopenharmony_ci#[cfg(any(target_os = "ios", target_os = "macos"))]
373da5c369Sopenharmony_ciuse std::os::unix::io::RawFd;
383da5c369Sopenharmony_ciuse std::path::Path;
393da5c369Sopenharmony_ciuse std::{fmt, mem, net, ptr, slice};
403da5c369Sopenharmony_ci
413da5c369Sopenharmony_ci/// Convert a std::net::Ipv4Addr into the libc form.
423da5c369Sopenharmony_ci#[cfg(feature = "net")]
433da5c369Sopenharmony_cipub(crate) const fn ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr {
443da5c369Sopenharmony_ci    static_assertions::assert_eq_size!(net::Ipv4Addr, libc::in_addr);
453da5c369Sopenharmony_ci    // Safe because both types have the same memory layout, and no fancy Drop
463da5c369Sopenharmony_ci    // impls.
473da5c369Sopenharmony_ci    unsafe {
483da5c369Sopenharmony_ci        mem::transmute(addr)
493da5c369Sopenharmony_ci    }
503da5c369Sopenharmony_ci}
513da5c369Sopenharmony_ci
523da5c369Sopenharmony_ci/// Convert a std::net::Ipv6Addr into the libc form.
533da5c369Sopenharmony_ci#[cfg(feature = "net")]
543da5c369Sopenharmony_cipub(crate) const fn ipv6addr_to_libc(addr: &net::Ipv6Addr) -> libc::in6_addr {
553da5c369Sopenharmony_ci    static_assertions::assert_eq_size!(net::Ipv6Addr, libc::in6_addr);
563da5c369Sopenharmony_ci    // Safe because both are Newtype wrappers around the same libc type
573da5c369Sopenharmony_ci    unsafe {
583da5c369Sopenharmony_ci        mem::transmute(*addr)
593da5c369Sopenharmony_ci    }
603da5c369Sopenharmony_ci}
613da5c369Sopenharmony_ci
623da5c369Sopenharmony_ci/// These constants specify the protocol family to be used
633da5c369Sopenharmony_ci/// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
643da5c369Sopenharmony_ci///
653da5c369Sopenharmony_ci/// # References
663da5c369Sopenharmony_ci///
673da5c369Sopenharmony_ci/// [address_families(7)](https://man7.org/linux/man-pages/man7/address_families.7.html)
683da5c369Sopenharmony_ci// Should this be u8?
693da5c369Sopenharmony_ci#[repr(i32)]
703da5c369Sopenharmony_ci#[non_exhaustive]
713da5c369Sopenharmony_ci#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
723da5c369Sopenharmony_cipub enum AddressFamily {
733da5c369Sopenharmony_ci    /// Local communication (see [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html))
743da5c369Sopenharmony_ci    Unix = libc::AF_UNIX,
753da5c369Sopenharmony_ci    /// IPv4 Internet protocols (see [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html))
763da5c369Sopenharmony_ci    Inet = libc::AF_INET,
773da5c369Sopenharmony_ci    /// IPv6 Internet protocols (see [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html))
783da5c369Sopenharmony_ci    Inet6 = libc::AF_INET6,
793da5c369Sopenharmony_ci    /// Kernel user interface device (see [`netlink(7)`](https://man7.org/linux/man-pages/man7/netlink.7.html))
803da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
813da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
823da5c369Sopenharmony_ci    Netlink = libc::AF_NETLINK,
833da5c369Sopenharmony_ci    /// Low level packet interface (see [`packet(7)`](https://man7.org/linux/man-pages/man7/packet.7.html))
843da5c369Sopenharmony_ci    #[cfg(any(
853da5c369Sopenharmony_ci        target_os = "android",
863da5c369Sopenharmony_ci        target_os = "linux",
873da5c369Sopenharmony_ci        target_os = "illumos",
883da5c369Sopenharmony_ci        target_os = "fuchsia",
893da5c369Sopenharmony_ci        target_os = "solaris"
903da5c369Sopenharmony_ci    ))]
913da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
923da5c369Sopenharmony_ci    Packet = libc::AF_PACKET,
933da5c369Sopenharmony_ci    /// KEXT Controls and Notifications
943da5c369Sopenharmony_ci    #[cfg(any(target_os = "ios", target_os = "macos"))]
953da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
963da5c369Sopenharmony_ci    System = libc::AF_SYSTEM,
973da5c369Sopenharmony_ci    /// Amateur radio AX.25 protocol
983da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
993da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1003da5c369Sopenharmony_ci    Ax25 = libc::AF_AX25,
1013da5c369Sopenharmony_ci    /// IPX - Novell protocols
1023da5c369Sopenharmony_ci    Ipx = libc::AF_IPX,
1033da5c369Sopenharmony_ci    /// AppleTalk
1043da5c369Sopenharmony_ci    AppleTalk = libc::AF_APPLETALK,
1053da5c369Sopenharmony_ci    /// AX.25 packet layer protocol.
1063da5c369Sopenharmony_ci    /// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/))
1073da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1083da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1093da5c369Sopenharmony_ci    NetRom = libc::AF_NETROM,
1103da5c369Sopenharmony_ci    /// Can't be used for creating sockets; mostly used for bridge
1113da5c369Sopenharmony_ci    /// links in
1123da5c369Sopenharmony_ci    /// [rtnetlink(7)](https://man7.org/linux/man-pages/man7/rtnetlink.7.html)
1133da5c369Sopenharmony_ci    /// protocol commands.
1143da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1153da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1163da5c369Sopenharmony_ci    Bridge = libc::AF_BRIDGE,
1173da5c369Sopenharmony_ci    /// Access to raw ATM PVCs
1183da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1193da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1203da5c369Sopenharmony_ci    AtmPvc = libc::AF_ATMPVC,
1213da5c369Sopenharmony_ci    /// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](https://man7.org/linux/man-pages/man7/x25.7.html))
1223da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1233da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1243da5c369Sopenharmony_ci    X25 = libc::AF_X25,
1253da5c369Sopenharmony_ci    /// RATS (Radio Amateur Telecommunications Society) Open
1263da5c369Sopenharmony_ci    /// Systems environment (ROSE) AX.25 packet layer protocol.
1273da5c369Sopenharmony_ci    /// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/))
1283da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1293da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1303da5c369Sopenharmony_ci    Rose = libc::AF_ROSE,
1313da5c369Sopenharmony_ci    /// DECet protocol sockets.
1323da5c369Sopenharmony_ci    #[cfg(not(target_os = "haiku"))]
1333da5c369Sopenharmony_ci    Decnet = libc::AF_DECnet,
1343da5c369Sopenharmony_ci    /// Reserved for "802.2LLC project"; never used.
1353da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1363da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1373da5c369Sopenharmony_ci    NetBeui = libc::AF_NETBEUI,
1383da5c369Sopenharmony_ci    /// This was a short-lived (between Linux 2.1.30 and
1393da5c369Sopenharmony_ci    /// 2.1.99pre2) protocol family for firewall upcalls.
1403da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1413da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1423da5c369Sopenharmony_ci    Security = libc::AF_SECURITY,
1433da5c369Sopenharmony_ci    /// Key management protocol.
1443da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1453da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1463da5c369Sopenharmony_ci    Key = libc::AF_KEY,
1473da5c369Sopenharmony_ci    #[allow(missing_docs)] // Not documented anywhere that I can find
1483da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1493da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1503da5c369Sopenharmony_ci    Ash = libc::AF_ASH,
1513da5c369Sopenharmony_ci    /// Acorn Econet protocol
1523da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1533da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1543da5c369Sopenharmony_ci    Econet = libc::AF_ECONET,
1553da5c369Sopenharmony_ci    /// Access to ATM Switched Virtual Circuits
1563da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1573da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1583da5c369Sopenharmony_ci    AtmSvc = libc::AF_ATMSVC,
1593da5c369Sopenharmony_ci    /// Reliable Datagram Sockets (RDS) protocol
1603da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1613da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1623da5c369Sopenharmony_ci    Rds = libc::AF_RDS,
1633da5c369Sopenharmony_ci    /// IBM SNA
1643da5c369Sopenharmony_ci    #[cfg(not(target_os = "haiku"))]
1653da5c369Sopenharmony_ci    Sna = libc::AF_SNA,
1663da5c369Sopenharmony_ci    /// Socket interface over IrDA
1673da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1683da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1693da5c369Sopenharmony_ci    Irda = libc::AF_IRDA,
1703da5c369Sopenharmony_ci    /// Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE)
1713da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1723da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1733da5c369Sopenharmony_ci    Pppox = libc::AF_PPPOX,
1743da5c369Sopenharmony_ci    /// Legacy protocol for wide area network (WAN) connectivity that was used
1753da5c369Sopenharmony_ci    /// by Sangoma WAN cards
1763da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1773da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1783da5c369Sopenharmony_ci    Wanpipe = libc::AF_WANPIPE,
1793da5c369Sopenharmony_ci    /// Logical link control (IEEE 802.2 LLC) protocol
1803da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1813da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1823da5c369Sopenharmony_ci    Llc = libc::AF_LLC,
1833da5c369Sopenharmony_ci    /// InfiniBand native addressing
1843da5c369Sopenharmony_ci    #[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
1853da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1863da5c369Sopenharmony_ci    Ib = libc::AF_IB,
1873da5c369Sopenharmony_ci    /// Multiprotocol Label Switching
1883da5c369Sopenharmony_ci    #[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
1893da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1903da5c369Sopenharmony_ci    Mpls = libc::AF_MPLS,
1913da5c369Sopenharmony_ci    /// Controller Area Network automotive bus protocol
1923da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1933da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1943da5c369Sopenharmony_ci    Can = libc::AF_CAN,
1953da5c369Sopenharmony_ci    /// TIPC, "cluster domain sockets" protocol
1963da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
1973da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
1983da5c369Sopenharmony_ci    Tipc = libc::AF_TIPC,
1993da5c369Sopenharmony_ci    /// Bluetooth low-level socket protocol
2003da5c369Sopenharmony_ci    #[cfg(not(any(
2013da5c369Sopenharmony_ci        target_os = "illumos",
2023da5c369Sopenharmony_ci        target_os = "ios",
2033da5c369Sopenharmony_ci        target_os = "macos",
2043da5c369Sopenharmony_ci        target_os = "solaris"
2053da5c369Sopenharmony_ci    )))]
2063da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
2073da5c369Sopenharmony_ci    Bluetooth = libc::AF_BLUETOOTH,
2083da5c369Sopenharmony_ci    /// IUCV (inter-user communication vehicle) z/VM protocol for
2093da5c369Sopenharmony_ci    /// hypervisor-guest interaction
2103da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
2113da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
2123da5c369Sopenharmony_ci    Iucv = libc::AF_IUCV,
2133da5c369Sopenharmony_ci    /// Rx, Andrew File System remote procedure call protocol
2143da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
2153da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
2163da5c369Sopenharmony_ci    RxRpc = libc::AF_RXRPC,
2173da5c369Sopenharmony_ci    /// New "modular ISDN" driver interface protocol
2183da5c369Sopenharmony_ci    #[cfg(not(any(
2193da5c369Sopenharmony_ci        target_os = "illumos",
2203da5c369Sopenharmony_ci        target_os = "solaris",
2213da5c369Sopenharmony_ci        target_os = "haiku"
2223da5c369Sopenharmony_ci    )))]
2233da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
2243da5c369Sopenharmony_ci    Isdn = libc::AF_ISDN,
2253da5c369Sopenharmony_ci    /// Nokia cellular modem IPC/RPC interface
2263da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
2273da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
2283da5c369Sopenharmony_ci    Phonet = libc::AF_PHONET,
2293da5c369Sopenharmony_ci    /// IEEE 802.15.4 WPAN (wireless personal area network) raw packet protocol
2303da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
2313da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
2323da5c369Sopenharmony_ci    Ieee802154 = libc::AF_IEEE802154,
2333da5c369Sopenharmony_ci    /// Ericsson's Communication CPU to Application CPU interface (CAIF)
2343da5c369Sopenharmony_ci    /// protocol.
2353da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
2363da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
2373da5c369Sopenharmony_ci    Caif = libc::AF_CAIF,
2383da5c369Sopenharmony_ci    /// Interface to kernel crypto API
2393da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
2403da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
2413da5c369Sopenharmony_ci    Alg = libc::AF_ALG,
2423da5c369Sopenharmony_ci    /// Near field communication
2433da5c369Sopenharmony_ci    #[cfg(target_os = "linux")]
2443da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
2453da5c369Sopenharmony_ci    Nfc = libc::AF_NFC,
2463da5c369Sopenharmony_ci    /// VMWare VSockets protocol for hypervisor-guest interaction.
2473da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
2483da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
2493da5c369Sopenharmony_ci    Vsock = libc::AF_VSOCK,
2503da5c369Sopenharmony_ci    /// ARPANet IMP addresses
2513da5c369Sopenharmony_ci    #[cfg(any(
2523da5c369Sopenharmony_ci        target_os = "dragonfly",
2533da5c369Sopenharmony_ci        target_os = "freebsd",
2543da5c369Sopenharmony_ci        target_os = "ios",
2553da5c369Sopenharmony_ci        target_os = "macos",
2563da5c369Sopenharmony_ci        target_os = "netbsd",
2573da5c369Sopenharmony_ci        target_os = "openbsd"
2583da5c369Sopenharmony_ci    ))]
2593da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
2603da5c369Sopenharmony_ci    ImpLink = libc::AF_IMPLINK,
2613da5c369Sopenharmony_ci    /// PUP protocols, e.g. BSP
2623da5c369Sopenharmony_ci    #[cfg(any(
2633da5c369Sopenharmony_ci        target_os = "dragonfly",
2643da5c369Sopenharmony_ci        target_os = "freebsd",
2653da5c369Sopenharmony_ci        target_os = "ios",
2663da5c369Sopenharmony_ci        target_os = "macos",
2673da5c369Sopenharmony_ci        target_os = "netbsd",
2683da5c369Sopenharmony_ci        target_os = "openbsd"
2693da5c369Sopenharmony_ci    ))]
2703da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
2713da5c369Sopenharmony_ci    Pup = libc::AF_PUP,
2723da5c369Sopenharmony_ci    /// MIT CHAOS protocols
2733da5c369Sopenharmony_ci    #[cfg(any(
2743da5c369Sopenharmony_ci        target_os = "dragonfly",
2753da5c369Sopenharmony_ci        target_os = "freebsd",
2763da5c369Sopenharmony_ci        target_os = "ios",
2773da5c369Sopenharmony_ci        target_os = "macos",
2783da5c369Sopenharmony_ci        target_os = "netbsd",
2793da5c369Sopenharmony_ci        target_os = "openbsd"
2803da5c369Sopenharmony_ci    ))]
2813da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
2823da5c369Sopenharmony_ci    Chaos = libc::AF_CHAOS,
2833da5c369Sopenharmony_ci    /// Novell and Xerox protocol
2843da5c369Sopenharmony_ci    #[cfg(any(
2853da5c369Sopenharmony_ci        target_os = "ios",
2863da5c369Sopenharmony_ci        target_os = "macos",
2873da5c369Sopenharmony_ci        target_os = "netbsd",
2883da5c369Sopenharmony_ci        target_os = "openbsd"
2893da5c369Sopenharmony_ci    ))]
2903da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
2913da5c369Sopenharmony_ci    Ns = libc::AF_NS,
2923da5c369Sopenharmony_ci    #[allow(missing_docs)] // Not documented anywhere that I can find
2933da5c369Sopenharmony_ci    #[cfg(any(
2943da5c369Sopenharmony_ci        target_os = "dragonfly",
2953da5c369Sopenharmony_ci        target_os = "freebsd",
2963da5c369Sopenharmony_ci        target_os = "ios",
2973da5c369Sopenharmony_ci        target_os = "macos",
2983da5c369Sopenharmony_ci        target_os = "netbsd",
2993da5c369Sopenharmony_ci        target_os = "openbsd"
3003da5c369Sopenharmony_ci    ))]
3013da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
3023da5c369Sopenharmony_ci    Iso = libc::AF_ISO,
3033da5c369Sopenharmony_ci    /// Bell Labs virtual circuit switch ?
3043da5c369Sopenharmony_ci    #[cfg(any(
3053da5c369Sopenharmony_ci        target_os = "dragonfly",
3063da5c369Sopenharmony_ci        target_os = "freebsd",
3073da5c369Sopenharmony_ci        target_os = "ios",
3083da5c369Sopenharmony_ci        target_os = "macos",
3093da5c369Sopenharmony_ci        target_os = "netbsd",
3103da5c369Sopenharmony_ci        target_os = "openbsd"
3113da5c369Sopenharmony_ci    ))]
3123da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
3133da5c369Sopenharmony_ci    Datakit = libc::AF_DATAKIT,
3143da5c369Sopenharmony_ci    /// CCITT protocols, X.25 etc
3153da5c369Sopenharmony_ci    #[cfg(any(
3163da5c369Sopenharmony_ci        target_os = "dragonfly",
3173da5c369Sopenharmony_ci        target_os = "freebsd",
3183da5c369Sopenharmony_ci        target_os = "ios",
3193da5c369Sopenharmony_ci        target_os = "macos",
3203da5c369Sopenharmony_ci        target_os = "netbsd",
3213da5c369Sopenharmony_ci        target_os = "openbsd"
3223da5c369Sopenharmony_ci    ))]
3233da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
3243da5c369Sopenharmony_ci    Ccitt = libc::AF_CCITT,
3253da5c369Sopenharmony_ci    /// DEC Direct data link interface
3263da5c369Sopenharmony_ci    #[cfg(any(
3273da5c369Sopenharmony_ci        target_os = "dragonfly",
3283da5c369Sopenharmony_ci        target_os = "freebsd",
3293da5c369Sopenharmony_ci        target_os = "ios",
3303da5c369Sopenharmony_ci        target_os = "macos",
3313da5c369Sopenharmony_ci        target_os = "netbsd",
3323da5c369Sopenharmony_ci        target_os = "openbsd"
3333da5c369Sopenharmony_ci    ))]
3343da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
3353da5c369Sopenharmony_ci    Dli = libc::AF_DLI,
3363da5c369Sopenharmony_ci    #[allow(missing_docs)] // Not documented anywhere that I can find
3373da5c369Sopenharmony_ci    #[cfg(any(
3383da5c369Sopenharmony_ci        target_os = "dragonfly",
3393da5c369Sopenharmony_ci        target_os = "freebsd",
3403da5c369Sopenharmony_ci        target_os = "ios",
3413da5c369Sopenharmony_ci        target_os = "macos",
3423da5c369Sopenharmony_ci        target_os = "netbsd",
3433da5c369Sopenharmony_ci        target_os = "openbsd"
3443da5c369Sopenharmony_ci    ))]
3453da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
3463da5c369Sopenharmony_ci    Lat = libc::AF_LAT,
3473da5c369Sopenharmony_ci    /// NSC Hyperchannel
3483da5c369Sopenharmony_ci    #[cfg(any(
3493da5c369Sopenharmony_ci        target_os = "dragonfly",
3503da5c369Sopenharmony_ci        target_os = "freebsd",
3513da5c369Sopenharmony_ci        target_os = "ios",
3523da5c369Sopenharmony_ci        target_os = "macos",
3533da5c369Sopenharmony_ci        target_os = "netbsd",
3543da5c369Sopenharmony_ci        target_os = "openbsd"
3553da5c369Sopenharmony_ci    ))]
3563da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
3573da5c369Sopenharmony_ci    Hylink = libc::AF_HYLINK,
3583da5c369Sopenharmony_ci    /// Link layer interface
3593da5c369Sopenharmony_ci    #[cfg(any(
3603da5c369Sopenharmony_ci        target_os = "dragonfly",
3613da5c369Sopenharmony_ci        target_os = "freebsd",
3623da5c369Sopenharmony_ci        target_os = "ios",
3633da5c369Sopenharmony_ci        target_os = "macos",
3643da5c369Sopenharmony_ci        target_os = "illumos",
3653da5c369Sopenharmony_ci        target_os = "netbsd",
3663da5c369Sopenharmony_ci        target_os = "openbsd"
3673da5c369Sopenharmony_ci    ))]
3683da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
3693da5c369Sopenharmony_ci    Link = libc::AF_LINK,
3703da5c369Sopenharmony_ci    /// connection-oriented IP, aka ST II
3713da5c369Sopenharmony_ci    #[cfg(any(
3723da5c369Sopenharmony_ci        target_os = "dragonfly",
3733da5c369Sopenharmony_ci        target_os = "freebsd",
3743da5c369Sopenharmony_ci        target_os = "ios",
3753da5c369Sopenharmony_ci        target_os = "macos",
3763da5c369Sopenharmony_ci        target_os = "netbsd",
3773da5c369Sopenharmony_ci        target_os = "openbsd"
3783da5c369Sopenharmony_ci    ))]
3793da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
3803da5c369Sopenharmony_ci    Coip = libc::AF_COIP,
3813da5c369Sopenharmony_ci    /// Computer Network Technology
3823da5c369Sopenharmony_ci    #[cfg(any(
3833da5c369Sopenharmony_ci        target_os = "dragonfly",
3843da5c369Sopenharmony_ci        target_os = "freebsd",
3853da5c369Sopenharmony_ci        target_os = "ios",
3863da5c369Sopenharmony_ci        target_os = "macos",
3873da5c369Sopenharmony_ci        target_os = "netbsd",
3883da5c369Sopenharmony_ci        target_os = "openbsd"
3893da5c369Sopenharmony_ci    ))]
3903da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
3913da5c369Sopenharmony_ci    Cnt = libc::AF_CNT,
3923da5c369Sopenharmony_ci    /// Native ATM access
3933da5c369Sopenharmony_ci    #[cfg(any(
3943da5c369Sopenharmony_ci        target_os = "dragonfly",
3953da5c369Sopenharmony_ci        target_os = "freebsd",
3963da5c369Sopenharmony_ci        target_os = "ios",
3973da5c369Sopenharmony_ci        target_os = "macos",
3983da5c369Sopenharmony_ci        target_os = "netbsd",
3993da5c369Sopenharmony_ci        target_os = "openbsd"
4003da5c369Sopenharmony_ci    ))]
4013da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
4023da5c369Sopenharmony_ci    Natm = libc::AF_NATM,
4033da5c369Sopenharmony_ci    /// Unspecified address family, (see [`getaddrinfo(3)`](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html))
4043da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
4053da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
4063da5c369Sopenharmony_ci    Unspec = libc::AF_UNSPEC,
4073da5c369Sopenharmony_ci}
4083da5c369Sopenharmony_ci
4093da5c369Sopenharmony_ciimpl AddressFamily {
4103da5c369Sopenharmony_ci    /// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from
4113da5c369Sopenharmony_ci    /// the `sa_family` field of a `sockaddr`.
4123da5c369Sopenharmony_ci    ///
4133da5c369Sopenharmony_ci    /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet
4143da5c369Sopenharmony_ci    /// and System. Returns None for unsupported or unknown address families.
4153da5c369Sopenharmony_ci    pub const fn from_i32(family: i32) -> Option<AddressFamily> {
4163da5c369Sopenharmony_ci        match family {
4173da5c369Sopenharmony_ci            libc::AF_UNIX => Some(AddressFamily::Unix),
4183da5c369Sopenharmony_ci            libc::AF_INET => Some(AddressFamily::Inet),
4193da5c369Sopenharmony_ci            libc::AF_INET6 => Some(AddressFamily::Inet6),
4203da5c369Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
4213da5c369Sopenharmony_ci            libc::AF_NETLINK => Some(AddressFamily::Netlink),
4223da5c369Sopenharmony_ci            #[cfg(any(target_os = "macos", target_os = "macos"))]
4233da5c369Sopenharmony_ci            libc::AF_SYSTEM => Some(AddressFamily::System),
4243da5c369Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
4253da5c369Sopenharmony_ci            libc::AF_PACKET => Some(AddressFamily::Packet),
4263da5c369Sopenharmony_ci            #[cfg(any(
4273da5c369Sopenharmony_ci                target_os = "dragonfly",
4283da5c369Sopenharmony_ci                target_os = "freebsd",
4293da5c369Sopenharmony_ci                target_os = "ios",
4303da5c369Sopenharmony_ci                target_os = "macos",
4313da5c369Sopenharmony_ci                target_os = "netbsd",
4323da5c369Sopenharmony_ci                target_os = "illumos",
4333da5c369Sopenharmony_ci                target_os = "openbsd"
4343da5c369Sopenharmony_ci            ))]
4353da5c369Sopenharmony_ci            libc::AF_LINK => Some(AddressFamily::Link),
4363da5c369Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
4373da5c369Sopenharmony_ci            libc::AF_VSOCK => Some(AddressFamily::Vsock),
4383da5c369Sopenharmony_ci            _ => None,
4393da5c369Sopenharmony_ci        }
4403da5c369Sopenharmony_ci    }
4413da5c369Sopenharmony_ci}
4423da5c369Sopenharmony_ci
4433da5c369Sopenharmony_cifeature! {
4443da5c369Sopenharmony_ci#![feature = "net"]
4453da5c369Sopenharmony_ci
4463da5c369Sopenharmony_ci#[deprecated(
4473da5c369Sopenharmony_ci    since = "0.24.0",
4483da5c369Sopenharmony_ci    note = "use SockaddrIn, SockaddrIn6, or SockaddrStorage instead"
4493da5c369Sopenharmony_ci)]
4503da5c369Sopenharmony_ci#[allow(missing_docs)]  // Since they're all deprecated anyway
4513da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
4523da5c369Sopenharmony_cipub enum InetAddr {
4533da5c369Sopenharmony_ci    V4(libc::sockaddr_in),
4543da5c369Sopenharmony_ci    V6(libc::sockaddr_in6),
4553da5c369Sopenharmony_ci}
4563da5c369Sopenharmony_ci
4573da5c369Sopenharmony_ci#[allow(missing_docs)]  // It's deprecated anyway
4583da5c369Sopenharmony_ci#[allow(deprecated)]
4593da5c369Sopenharmony_ciimpl InetAddr {
4603da5c369Sopenharmony_ci    #[allow(clippy::needless_update)]   // It isn't needless on all OSes
4613da5c369Sopenharmony_ci    pub fn from_std(std: &net::SocketAddr) -> InetAddr {
4623da5c369Sopenharmony_ci        match *std {
4633da5c369Sopenharmony_ci            net::SocketAddr::V4(ref addr) => {
4643da5c369Sopenharmony_ci                InetAddr::V4(libc::sockaddr_in {
4653da5c369Sopenharmony_ci                    #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
4663da5c369Sopenharmony_ci                              target_os = "haiku", target_os = "hermit",
4673da5c369Sopenharmony_ci                              target_os = "ios", target_os = "macos",
4683da5c369Sopenharmony_ci                              target_os = "netbsd", target_os = "openbsd"))]
4693da5c369Sopenharmony_ci                    sin_len: mem::size_of::<libc::sockaddr_in>() as u8,
4703da5c369Sopenharmony_ci                    sin_family: AddressFamily::Inet as sa_family_t,
4713da5c369Sopenharmony_ci                    sin_port: addr.port().to_be(),  // network byte order
4723da5c369Sopenharmony_ci                    sin_addr: Ipv4Addr::from_std(addr.ip()).0,
4733da5c369Sopenharmony_ci                    .. unsafe { mem::zeroed() }
4743da5c369Sopenharmony_ci                })
4753da5c369Sopenharmony_ci            }
4763da5c369Sopenharmony_ci            net::SocketAddr::V6(ref addr) => {
4773da5c369Sopenharmony_ci                InetAddr::V6(libc::sockaddr_in6 {
4783da5c369Sopenharmony_ci                    #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
4793da5c369Sopenharmony_ci                              target_os = "haiku", target_os = "hermit",
4803da5c369Sopenharmony_ci                              target_os = "ios", target_os = "macos",
4813da5c369Sopenharmony_ci                              target_os = "netbsd", target_os = "openbsd"))]
4823da5c369Sopenharmony_ci                    sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8,
4833da5c369Sopenharmony_ci                    sin6_family: AddressFamily::Inet6 as sa_family_t,
4843da5c369Sopenharmony_ci                    sin6_port: addr.port().to_be(),  // network byte order
4853da5c369Sopenharmony_ci                    sin6_addr: Ipv6Addr::from_std(addr.ip()).0,
4863da5c369Sopenharmony_ci                    sin6_flowinfo: addr.flowinfo(),  // host byte order
4873da5c369Sopenharmony_ci                    sin6_scope_id: addr.scope_id(),  // host byte order
4883da5c369Sopenharmony_ci                    .. unsafe { mem::zeroed() }
4893da5c369Sopenharmony_ci                })
4903da5c369Sopenharmony_ci            }
4913da5c369Sopenharmony_ci        }
4923da5c369Sopenharmony_ci    }
4933da5c369Sopenharmony_ci
4943da5c369Sopenharmony_ci    #[allow(clippy::needless_update)]   // It isn't needless on all OSes
4953da5c369Sopenharmony_ci    pub fn new(ip: IpAddr, port: u16) -> InetAddr {
4963da5c369Sopenharmony_ci        match ip {
4973da5c369Sopenharmony_ci            IpAddr::V4(ref ip) => {
4983da5c369Sopenharmony_ci                InetAddr::V4(libc::sockaddr_in {
4993da5c369Sopenharmony_ci                    sin_family: AddressFamily::Inet as sa_family_t,
5003da5c369Sopenharmony_ci                    sin_port: port.to_be(),
5013da5c369Sopenharmony_ci                    sin_addr: ip.0,
5023da5c369Sopenharmony_ci                    .. unsafe { mem::zeroed() }
5033da5c369Sopenharmony_ci                })
5043da5c369Sopenharmony_ci            }
5053da5c369Sopenharmony_ci            IpAddr::V6(ref ip) => {
5063da5c369Sopenharmony_ci                InetAddr::V6(libc::sockaddr_in6 {
5073da5c369Sopenharmony_ci                    sin6_family: AddressFamily::Inet6 as sa_family_t,
5083da5c369Sopenharmony_ci                    sin6_port: port.to_be(),
5093da5c369Sopenharmony_ci                    sin6_addr: ip.0,
5103da5c369Sopenharmony_ci                    .. unsafe { mem::zeroed() }
5113da5c369Sopenharmony_ci                })
5123da5c369Sopenharmony_ci            }
5133da5c369Sopenharmony_ci        }
5143da5c369Sopenharmony_ci    }
5153da5c369Sopenharmony_ci    /// Gets the IP address associated with this socket address.
5163da5c369Sopenharmony_ci    pub const fn ip(&self) -> IpAddr {
5173da5c369Sopenharmony_ci        match *self {
5183da5c369Sopenharmony_ci            InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)),
5193da5c369Sopenharmony_ci            InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)),
5203da5c369Sopenharmony_ci        }
5213da5c369Sopenharmony_ci    }
5223da5c369Sopenharmony_ci
5233da5c369Sopenharmony_ci    /// Gets the port number associated with this socket address
5243da5c369Sopenharmony_ci    pub const fn port(&self) -> u16 {
5253da5c369Sopenharmony_ci        match *self {
5263da5c369Sopenharmony_ci            InetAddr::V6(ref sa) => u16::from_be(sa.sin6_port),
5273da5c369Sopenharmony_ci            InetAddr::V4(ref sa) => u16::from_be(sa.sin_port),
5283da5c369Sopenharmony_ci        }
5293da5c369Sopenharmony_ci    }
5303da5c369Sopenharmony_ci
5313da5c369Sopenharmony_ci    pub fn to_std(&self) -> net::SocketAddr {
5323da5c369Sopenharmony_ci        match *self {
5333da5c369Sopenharmony_ci            InetAddr::V4(ref sa) => net::SocketAddr::V4(
5343da5c369Sopenharmony_ci                net::SocketAddrV4::new(
5353da5c369Sopenharmony_ci                    Ipv4Addr(sa.sin_addr).to_std(),
5363da5c369Sopenharmony_ci                    self.port())),
5373da5c369Sopenharmony_ci            InetAddr::V6(ref sa) => net::SocketAddr::V6(
5383da5c369Sopenharmony_ci                net::SocketAddrV6::new(
5393da5c369Sopenharmony_ci                    Ipv6Addr(sa.sin6_addr).to_std(),
5403da5c369Sopenharmony_ci                    self.port(),
5413da5c369Sopenharmony_ci                    sa.sin6_flowinfo,
5423da5c369Sopenharmony_ci                    sa.sin6_scope_id)),
5433da5c369Sopenharmony_ci        }
5443da5c369Sopenharmony_ci    }
5453da5c369Sopenharmony_ci
5463da5c369Sopenharmony_ci    #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
5473da5c369Sopenharmony_ci    pub fn to_str(&self) -> String {
5483da5c369Sopenharmony_ci        format!("{}", self)
5493da5c369Sopenharmony_ci    }
5503da5c369Sopenharmony_ci}
5513da5c369Sopenharmony_ci
5523da5c369Sopenharmony_ci#[allow(deprecated)]
5533da5c369Sopenharmony_ciimpl fmt::Display for InetAddr {
5543da5c369Sopenharmony_ci    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5553da5c369Sopenharmony_ci        match *self {
5563da5c369Sopenharmony_ci            InetAddr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()),
5573da5c369Sopenharmony_ci            InetAddr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()),
5583da5c369Sopenharmony_ci        }
5593da5c369Sopenharmony_ci    }
5603da5c369Sopenharmony_ci}
5613da5c369Sopenharmony_ci
5623da5c369Sopenharmony_ci/*
5633da5c369Sopenharmony_ci *
5643da5c369Sopenharmony_ci * ===== IpAddr =====
5653da5c369Sopenharmony_ci *
5663da5c369Sopenharmony_ci */
5673da5c369Sopenharmony_ci#[allow(missing_docs)]  // Since they're all deprecated anyway
5683da5c369Sopenharmony_ci#[allow(deprecated)]
5693da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
5703da5c369Sopenharmony_ci#[deprecated(
5713da5c369Sopenharmony_ci    since = "0.24.0",
5723da5c369Sopenharmony_ci    note = "Use std::net::IpAddr instead"
5733da5c369Sopenharmony_ci)]
5743da5c369Sopenharmony_cipub enum IpAddr {
5753da5c369Sopenharmony_ci    V4(Ipv4Addr),
5763da5c369Sopenharmony_ci    V6(Ipv6Addr),
5773da5c369Sopenharmony_ci}
5783da5c369Sopenharmony_ci
5793da5c369Sopenharmony_ci#[allow(deprecated)]
5803da5c369Sopenharmony_ci#[allow(missing_docs)]  // Since they're all deprecated anyway
5813da5c369Sopenharmony_ciimpl IpAddr {
5823da5c369Sopenharmony_ci    /// Create a new IpAddr that contains an IPv4 address.
5833da5c369Sopenharmony_ci    ///
5843da5c369Sopenharmony_ci    /// The result will represent the IP address a.b.c.d
5853da5c369Sopenharmony_ci    pub const fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr {
5863da5c369Sopenharmony_ci        IpAddr::V4(Ipv4Addr::new(a, b, c, d))
5873da5c369Sopenharmony_ci    }
5883da5c369Sopenharmony_ci
5893da5c369Sopenharmony_ci    /// Create a new IpAddr that contains an IPv6 address.
5903da5c369Sopenharmony_ci    ///
5913da5c369Sopenharmony_ci    /// The result will represent the IP address a:b:c:d:e:f
5923da5c369Sopenharmony_ci    #[allow(clippy::many_single_char_names)]
5933da5c369Sopenharmony_ci    #[allow(clippy::too_many_arguments)]
5943da5c369Sopenharmony_ci    pub const fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
5953da5c369Sopenharmony_ci        IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
5963da5c369Sopenharmony_ci    }
5973da5c369Sopenharmony_ci
5983da5c369Sopenharmony_ci    pub fn from_std(std: &net::IpAddr) -> IpAddr {
5993da5c369Sopenharmony_ci        match *std {
6003da5c369Sopenharmony_ci            net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)),
6013da5c369Sopenharmony_ci            net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)),
6023da5c369Sopenharmony_ci        }
6033da5c369Sopenharmony_ci    }
6043da5c369Sopenharmony_ci
6053da5c369Sopenharmony_ci    pub const fn to_std(&self) -> net::IpAddr {
6063da5c369Sopenharmony_ci        match *self {
6073da5c369Sopenharmony_ci            IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()),
6083da5c369Sopenharmony_ci            IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()),
6093da5c369Sopenharmony_ci        }
6103da5c369Sopenharmony_ci    }
6113da5c369Sopenharmony_ci}
6123da5c369Sopenharmony_ci
6133da5c369Sopenharmony_ci#[allow(deprecated)]
6143da5c369Sopenharmony_ciimpl fmt::Display for IpAddr {
6153da5c369Sopenharmony_ci    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6163da5c369Sopenharmony_ci        match *self {
6173da5c369Sopenharmony_ci            IpAddr::V4(ref v4) => v4.fmt(f),
6183da5c369Sopenharmony_ci            IpAddr::V6(ref v6) => v6.fmt(f)
6193da5c369Sopenharmony_ci        }
6203da5c369Sopenharmony_ci    }
6213da5c369Sopenharmony_ci}
6223da5c369Sopenharmony_ci
6233da5c369Sopenharmony_ci/*
6243da5c369Sopenharmony_ci *
6253da5c369Sopenharmony_ci * ===== Ipv4Addr =====
6263da5c369Sopenharmony_ci *
6273da5c369Sopenharmony_ci */
6283da5c369Sopenharmony_ci
6293da5c369Sopenharmony_ci#[deprecated(
6303da5c369Sopenharmony_ci    since = "0.24.0",
6313da5c369Sopenharmony_ci    note = "Use std::net::Ipv4Addr instead"
6323da5c369Sopenharmony_ci)]
6333da5c369Sopenharmony_ci#[allow(missing_docs)]  // Since they're all deprecated anyway
6343da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
6353da5c369Sopenharmony_ci#[repr(transparent)]
6363da5c369Sopenharmony_cipub struct Ipv4Addr(pub libc::in_addr);
6373da5c369Sopenharmony_ci
6383da5c369Sopenharmony_ci#[allow(deprecated)]
6393da5c369Sopenharmony_ci#[allow(missing_docs)]  // Since they're all deprecated anyway
6403da5c369Sopenharmony_ciimpl Ipv4Addr {
6413da5c369Sopenharmony_ci    #[allow(clippy::identity_op)]   // More readable this way
6423da5c369Sopenharmony_ci    pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
6433da5c369Sopenharmony_ci        let ip = (((a as u32) << 24) |
6443da5c369Sopenharmony_ci                  ((b as u32) << 16) |
6453da5c369Sopenharmony_ci                  ((c as u32) <<  8) |
6463da5c369Sopenharmony_ci                  ((d as u32) <<  0)).to_be();
6473da5c369Sopenharmony_ci
6483da5c369Sopenharmony_ci        Ipv4Addr(libc::in_addr { s_addr: ip })
6493da5c369Sopenharmony_ci    }
6503da5c369Sopenharmony_ci
6513da5c369Sopenharmony_ci    // Use pass by reference for symmetry with Ipv6Addr::from_std
6523da5c369Sopenharmony_ci    #[allow(clippy::trivially_copy_pass_by_ref)]
6533da5c369Sopenharmony_ci    pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr {
6543da5c369Sopenharmony_ci        let bits = std.octets();
6553da5c369Sopenharmony_ci        Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
6563da5c369Sopenharmony_ci    }
6573da5c369Sopenharmony_ci
6583da5c369Sopenharmony_ci    pub const fn any() -> Ipv4Addr {
6593da5c369Sopenharmony_ci        Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY })
6603da5c369Sopenharmony_ci    }
6613da5c369Sopenharmony_ci
6623da5c369Sopenharmony_ci    pub const fn octets(self) -> [u8; 4] {
6633da5c369Sopenharmony_ci        let bits = u32::from_be(self.0.s_addr);
6643da5c369Sopenharmony_ci        [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
6653da5c369Sopenharmony_ci    }
6663da5c369Sopenharmony_ci
6673da5c369Sopenharmony_ci    pub const fn to_std(self) -> net::Ipv4Addr {
6683da5c369Sopenharmony_ci        let bits = self.octets();
6693da5c369Sopenharmony_ci        net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
6703da5c369Sopenharmony_ci    }
6713da5c369Sopenharmony_ci}
6723da5c369Sopenharmony_ci
6733da5c369Sopenharmony_ci#[allow(deprecated)]
6743da5c369Sopenharmony_ciimpl fmt::Display for Ipv4Addr {
6753da5c369Sopenharmony_ci    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
6763da5c369Sopenharmony_ci        let octets = self.octets();
6773da5c369Sopenharmony_ci        write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
6783da5c369Sopenharmony_ci    }
6793da5c369Sopenharmony_ci}
6803da5c369Sopenharmony_ci
6813da5c369Sopenharmony_ci/*
6823da5c369Sopenharmony_ci *
6833da5c369Sopenharmony_ci * ===== Ipv6Addr =====
6843da5c369Sopenharmony_ci *
6853da5c369Sopenharmony_ci */
6863da5c369Sopenharmony_ci
6873da5c369Sopenharmony_ci#[deprecated(
6883da5c369Sopenharmony_ci    since = "0.24.0",
6893da5c369Sopenharmony_ci    note = "Use std::net::Ipv6Addr instead"
6903da5c369Sopenharmony_ci)]
6913da5c369Sopenharmony_ci#[allow(missing_docs)]  // Since they're all deprecated anyway
6923da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
6933da5c369Sopenharmony_ci#[repr(transparent)]
6943da5c369Sopenharmony_cipub struct Ipv6Addr(pub libc::in6_addr);
6953da5c369Sopenharmony_ci
6963da5c369Sopenharmony_ci// Note that IPv6 addresses are stored in big endian order on all architectures.
6973da5c369Sopenharmony_ci// See https://tools.ietf.org/html/rfc1700 or consult your favorite search
6983da5c369Sopenharmony_ci// engine.
6993da5c369Sopenharmony_ci
7003da5c369Sopenharmony_cimacro_rules! to_u8_array {
7013da5c369Sopenharmony_ci    ($($num:ident),*) => {
7023da5c369Sopenharmony_ci        [ $(($num>>8) as u8, ($num&0xff) as u8,)* ]
7033da5c369Sopenharmony_ci    }
7043da5c369Sopenharmony_ci}
7053da5c369Sopenharmony_ci
7063da5c369Sopenharmony_cimacro_rules! to_u16_array {
7073da5c369Sopenharmony_ci    ($slf:ident, $($first:expr, $second:expr),*) => {
7083da5c369Sopenharmony_ci        [$( (($slf.0.s6_addr[$first] as u16) << 8) + $slf.0.s6_addr[$second] as u16,)*]
7093da5c369Sopenharmony_ci    }
7103da5c369Sopenharmony_ci}
7113da5c369Sopenharmony_ci
7123da5c369Sopenharmony_ci#[allow(deprecated)]
7133da5c369Sopenharmony_ci#[allow(missing_docs)]  // Since they're all deprecated anyway
7143da5c369Sopenharmony_ciimpl Ipv6Addr {
7153da5c369Sopenharmony_ci    #[allow(clippy::many_single_char_names)]
7163da5c369Sopenharmony_ci    #[allow(clippy::too_many_arguments)]
7173da5c369Sopenharmony_ci    pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
7183da5c369Sopenharmony_ci        Ipv6Addr(libc::in6_addr{s6_addr: to_u8_array!(a,b,c,d,e,f,g,h)})
7193da5c369Sopenharmony_ci    }
7203da5c369Sopenharmony_ci
7213da5c369Sopenharmony_ci    pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr {
7223da5c369Sopenharmony_ci        let s = std.segments();
7233da5c369Sopenharmony_ci        Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
7243da5c369Sopenharmony_ci    }
7253da5c369Sopenharmony_ci
7263da5c369Sopenharmony_ci    /// Return the eight 16-bit segments that make up this address
7273da5c369Sopenharmony_ci    pub const fn segments(&self) -> [u16; 8] {
7283da5c369Sopenharmony_ci        to_u16_array!(self, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
7293da5c369Sopenharmony_ci    }
7303da5c369Sopenharmony_ci
7313da5c369Sopenharmony_ci    pub const fn to_std(&self) -> net::Ipv6Addr {
7323da5c369Sopenharmony_ci        let s = self.segments();
7333da5c369Sopenharmony_ci        net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
7343da5c369Sopenharmony_ci    }
7353da5c369Sopenharmony_ci}
7363da5c369Sopenharmony_ci
7373da5c369Sopenharmony_ci#[allow(deprecated)]
7383da5c369Sopenharmony_ciimpl fmt::Display for Ipv6Addr {
7393da5c369Sopenharmony_ci    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
7403da5c369Sopenharmony_ci        self.to_std().fmt(fmt)
7413da5c369Sopenharmony_ci    }
7423da5c369Sopenharmony_ci}
7433da5c369Sopenharmony_ci}
7443da5c369Sopenharmony_ci
7453da5c369Sopenharmony_ci/// A wrapper around `sockaddr_un`.
7463da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug)]
7473da5c369Sopenharmony_ci#[repr(C)]
7483da5c369Sopenharmony_cipub struct UnixAddr {
7493da5c369Sopenharmony_ci    // INVARIANT: sun & sun_len are valid as defined by docs for from_raw_parts
7503da5c369Sopenharmony_ci    sun: libc::sockaddr_un,
7513da5c369Sopenharmony_ci    /// The length of the valid part of `sun`, including the sun_family field
7523da5c369Sopenharmony_ci    /// but excluding any trailing nul.
7533da5c369Sopenharmony_ci    // On the BSDs, this field is built into sun
7543da5c369Sopenharmony_ci    #[cfg(any(
7553da5c369Sopenharmony_ci        target_os = "android",
7563da5c369Sopenharmony_ci        target_os = "fuchsia",
7573da5c369Sopenharmony_ci        target_os = "illumos",
7583da5c369Sopenharmony_ci        target_os = "linux"
7593da5c369Sopenharmony_ci    ))]
7603da5c369Sopenharmony_ci    sun_len: u8,
7613da5c369Sopenharmony_ci}
7623da5c369Sopenharmony_ci
7633da5c369Sopenharmony_ci// linux man page unix(7) says there are 3 kinds of unix socket:
7643da5c369Sopenharmony_ci// pathname: addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1
7653da5c369Sopenharmony_ci// unnamed: addrlen = sizeof(sa_family_t)
7663da5c369Sopenharmony_ci// abstract: addren > sizeof(sa_family_t), name = sun_path[..(addrlen - sizeof(sa_family_t))]
7673da5c369Sopenharmony_ci//
7683da5c369Sopenharmony_ci// what we call path_len = addrlen - offsetof(struct sockaddr_un, sun_path)
7693da5c369Sopenharmony_ci#[derive(PartialEq, Eq, Hash)]
7703da5c369Sopenharmony_cienum UnixAddrKind<'a> {
7713da5c369Sopenharmony_ci    Pathname(&'a Path),
7723da5c369Sopenharmony_ci    Unnamed,
7733da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
7743da5c369Sopenharmony_ci    Abstract(&'a [u8]),
7753da5c369Sopenharmony_ci}
7763da5c369Sopenharmony_ciimpl<'a> UnixAddrKind<'a> {
7773da5c369Sopenharmony_ci    /// Safety: sun & sun_len must be valid
7783da5c369Sopenharmony_ci    unsafe fn get(sun: &'a libc::sockaddr_un, sun_len: u8) -> Self {
7793da5c369Sopenharmony_ci        assert!(sun_len as usize >= offset_of!(libc::sockaddr_un, sun_path));
7803da5c369Sopenharmony_ci        let path_len =
7813da5c369Sopenharmony_ci            sun_len as usize - offset_of!(libc::sockaddr_un, sun_path);
7823da5c369Sopenharmony_ci        if path_len == 0 {
7833da5c369Sopenharmony_ci            return Self::Unnamed;
7843da5c369Sopenharmony_ci        }
7853da5c369Sopenharmony_ci        #[cfg(any(target_os = "android", target_os = "linux"))]
7863da5c369Sopenharmony_ci        if sun.sun_path[0] == 0 {
7873da5c369Sopenharmony_ci            let name = slice::from_raw_parts(
7883da5c369Sopenharmony_ci                sun.sun_path.as_ptr().add(1) as *const u8,
7893da5c369Sopenharmony_ci                path_len - 1,
7903da5c369Sopenharmony_ci            );
7913da5c369Sopenharmony_ci            return Self::Abstract(name);
7923da5c369Sopenharmony_ci        }
7933da5c369Sopenharmony_ci        let pathname =
7943da5c369Sopenharmony_ci            slice::from_raw_parts(sun.sun_path.as_ptr() as *const u8, path_len);
7953da5c369Sopenharmony_ci        if pathname.last() == Some(&0) {
7963da5c369Sopenharmony_ci            // A trailing NUL is not considered part of the path, and it does
7973da5c369Sopenharmony_ci            // not need to be included in the addrlen passed to functions like
7983da5c369Sopenharmony_ci            // bind().  However, Linux adds a trailing NUL, even if one was not
7993da5c369Sopenharmony_ci            // originally present, when returning addrs from functions like
8003da5c369Sopenharmony_ci            // getsockname() (the BSDs do not do that).  So we need to filter
8013da5c369Sopenharmony_ci            // out any trailing NUL here, so sockaddrs can round-trip through
8023da5c369Sopenharmony_ci            // the kernel and still compare equal.
8033da5c369Sopenharmony_ci            Self::Pathname(Path::new(OsStr::from_bytes(
8043da5c369Sopenharmony_ci                &pathname[0..pathname.len() - 1],
8053da5c369Sopenharmony_ci            )))
8063da5c369Sopenharmony_ci        } else {
8073da5c369Sopenharmony_ci            Self::Pathname(Path::new(OsStr::from_bytes(pathname)))
8083da5c369Sopenharmony_ci        }
8093da5c369Sopenharmony_ci    }
8103da5c369Sopenharmony_ci}
8113da5c369Sopenharmony_ci
8123da5c369Sopenharmony_ciimpl UnixAddr {
8133da5c369Sopenharmony_ci    /// Create a new sockaddr_un representing a filesystem path.
8143da5c369Sopenharmony_ci    pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
8153da5c369Sopenharmony_ci        path.with_nix_path(|cstr| unsafe {
8163da5c369Sopenharmony_ci            let mut ret = libc::sockaddr_un {
8173da5c369Sopenharmony_ci                sun_family: AddressFamily::Unix as sa_family_t,
8183da5c369Sopenharmony_ci                ..mem::zeroed()
8193da5c369Sopenharmony_ci            };
8203da5c369Sopenharmony_ci
8213da5c369Sopenharmony_ci            let bytes = cstr.to_bytes();
8223da5c369Sopenharmony_ci
8233da5c369Sopenharmony_ci            if bytes.len() >= ret.sun_path.len() {
8243da5c369Sopenharmony_ci                return Err(Errno::ENAMETOOLONG);
8253da5c369Sopenharmony_ci            }
8263da5c369Sopenharmony_ci
8273da5c369Sopenharmony_ci            let sun_len = (bytes.len()
8283da5c369Sopenharmony_ci                + offset_of!(libc::sockaddr_un, sun_path))
8293da5c369Sopenharmony_ci            .try_into()
8303da5c369Sopenharmony_ci            .unwrap();
8313da5c369Sopenharmony_ci
8323da5c369Sopenharmony_ci            #[cfg(any(
8333da5c369Sopenharmony_ci                target_os = "dragonfly",
8343da5c369Sopenharmony_ci                target_os = "freebsd",
8353da5c369Sopenharmony_ci                target_os = "ios",
8363da5c369Sopenharmony_ci                target_os = "macos",
8373da5c369Sopenharmony_ci                target_os = "netbsd",
8383da5c369Sopenharmony_ci                target_os = "openbsd"
8393da5c369Sopenharmony_ci            ))]
8403da5c369Sopenharmony_ci            {
8413da5c369Sopenharmony_ci                ret.sun_len = sun_len;
8423da5c369Sopenharmony_ci            }
8433da5c369Sopenharmony_ci            ptr::copy_nonoverlapping(
8443da5c369Sopenharmony_ci                bytes.as_ptr(),
8453da5c369Sopenharmony_ci                ret.sun_path.as_mut_ptr() as *mut u8,
8463da5c369Sopenharmony_ci                bytes.len(),
8473da5c369Sopenharmony_ci            );
8483da5c369Sopenharmony_ci
8493da5c369Sopenharmony_ci            Ok(UnixAddr::from_raw_parts(ret, sun_len))
8503da5c369Sopenharmony_ci        })?
8513da5c369Sopenharmony_ci    }
8523da5c369Sopenharmony_ci
8533da5c369Sopenharmony_ci    /// Create a new `sockaddr_un` representing an address in the "abstract namespace".
8543da5c369Sopenharmony_ci    ///
8553da5c369Sopenharmony_ci    /// The leading nul byte for the abstract namespace is automatically added;
8563da5c369Sopenharmony_ci    /// thus the input `path` is expected to be the bare name, not NUL-prefixed.
8573da5c369Sopenharmony_ci    /// This is a Linux-specific extension, primarily used to allow chrooted
8583da5c369Sopenharmony_ci    /// processes to communicate with processes having a different filesystem view.
8593da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
8603da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
8613da5c369Sopenharmony_ci    pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
8623da5c369Sopenharmony_ci        unsafe {
8633da5c369Sopenharmony_ci            let mut ret = libc::sockaddr_un {
8643da5c369Sopenharmony_ci                sun_family: AddressFamily::Unix as sa_family_t,
8653da5c369Sopenharmony_ci                ..mem::zeroed()
8663da5c369Sopenharmony_ci            };
8673da5c369Sopenharmony_ci
8683da5c369Sopenharmony_ci            if path.len() >= ret.sun_path.len() {
8693da5c369Sopenharmony_ci                return Err(Errno::ENAMETOOLONG);
8703da5c369Sopenharmony_ci            }
8713da5c369Sopenharmony_ci            let sun_len =
8723da5c369Sopenharmony_ci                (path.len() + 1 + offset_of!(libc::sockaddr_un, sun_path))
8733da5c369Sopenharmony_ci                    .try_into()
8743da5c369Sopenharmony_ci                    .unwrap();
8753da5c369Sopenharmony_ci
8763da5c369Sopenharmony_ci            // Abstract addresses are represented by sun_path[0] ==
8773da5c369Sopenharmony_ci            // b'\0', so copy starting one byte in.
8783da5c369Sopenharmony_ci            ptr::copy_nonoverlapping(
8793da5c369Sopenharmony_ci                path.as_ptr(),
8803da5c369Sopenharmony_ci                ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
8813da5c369Sopenharmony_ci                path.len(),
8823da5c369Sopenharmony_ci            );
8833da5c369Sopenharmony_ci
8843da5c369Sopenharmony_ci            Ok(UnixAddr::from_raw_parts(ret, sun_len))
8853da5c369Sopenharmony_ci        }
8863da5c369Sopenharmony_ci    }
8873da5c369Sopenharmony_ci
8883da5c369Sopenharmony_ci    /// Create a new `sockaddr_un` representing an "unnamed" unix socket address.
8893da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
8903da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
8913da5c369Sopenharmony_ci    pub fn new_unnamed() -> UnixAddr {
8923da5c369Sopenharmony_ci        let ret = libc::sockaddr_un {
8933da5c369Sopenharmony_ci            sun_family: AddressFamily::Unix as sa_family_t,
8943da5c369Sopenharmony_ci            .. unsafe { mem::zeroed() }
8953da5c369Sopenharmony_ci        };
8963da5c369Sopenharmony_ci
8973da5c369Sopenharmony_ci        let sun_len: u8 = offset_of!(libc::sockaddr_un, sun_path).try_into().unwrap();
8983da5c369Sopenharmony_ci
8993da5c369Sopenharmony_ci        unsafe { UnixAddr::from_raw_parts(ret, sun_len) }
9003da5c369Sopenharmony_ci    }
9013da5c369Sopenharmony_ci
9023da5c369Sopenharmony_ci    /// Create a UnixAddr from a raw `sockaddr_un` struct and a size. `sun_len`
9033da5c369Sopenharmony_ci    /// is the size of the valid portion of the struct, excluding any trailing
9043da5c369Sopenharmony_ci    /// NUL.
9053da5c369Sopenharmony_ci    ///
9063da5c369Sopenharmony_ci    /// # Safety
9073da5c369Sopenharmony_ci    /// This pair of sockaddr_un & sun_len must be a valid unix addr, which
9083da5c369Sopenharmony_ci    /// means:
9093da5c369Sopenharmony_ci    /// - sun_len >= offset_of(sockaddr_un, sun_path)
9103da5c369Sopenharmony_ci    /// - sun_len <= sockaddr_un.sun_path.len() - offset_of(sockaddr_un, sun_path)
9113da5c369Sopenharmony_ci    /// - if this is a unix addr with a pathname, sun.sun_path is a
9123da5c369Sopenharmony_ci    ///   fs path, not necessarily nul-terminated.
9133da5c369Sopenharmony_ci    pub(crate) unsafe fn from_raw_parts(
9143da5c369Sopenharmony_ci        sun: libc::sockaddr_un,
9153da5c369Sopenharmony_ci        sun_len: u8,
9163da5c369Sopenharmony_ci    ) -> UnixAddr {
9173da5c369Sopenharmony_ci        cfg_if! {
9183da5c369Sopenharmony_ci            if #[cfg(any(target_os = "android",
9193da5c369Sopenharmony_ci                     target_os = "fuchsia",
9203da5c369Sopenharmony_ci                     target_os = "illumos",
9213da5c369Sopenharmony_ci                     target_os = "linux"
9223da5c369Sopenharmony_ci                ))]
9233da5c369Sopenharmony_ci            {
9243da5c369Sopenharmony_ci                UnixAddr { sun, sun_len }
9253da5c369Sopenharmony_ci            } else {
9263da5c369Sopenharmony_ci                assert_eq!(sun_len, sun.sun_len);
9273da5c369Sopenharmony_ci                UnixAddr {sun}
9283da5c369Sopenharmony_ci            }
9293da5c369Sopenharmony_ci        }
9303da5c369Sopenharmony_ci    }
9313da5c369Sopenharmony_ci
9323da5c369Sopenharmony_ci    fn kind(&self) -> UnixAddrKind<'_> {
9333da5c369Sopenharmony_ci        // SAFETY: our sockaddr is always valid because of the invariant on the struct
9343da5c369Sopenharmony_ci        unsafe { UnixAddrKind::get(&self.sun, self.sun_len()) }
9353da5c369Sopenharmony_ci    }
9363da5c369Sopenharmony_ci
9373da5c369Sopenharmony_ci    /// If this address represents a filesystem path, return that path.
9383da5c369Sopenharmony_ci    pub fn path(&self) -> Option<&Path> {
9393da5c369Sopenharmony_ci        match self.kind() {
9403da5c369Sopenharmony_ci            UnixAddrKind::Pathname(path) => Some(path),
9413da5c369Sopenharmony_ci            _ => None,
9423da5c369Sopenharmony_ci        }
9433da5c369Sopenharmony_ci    }
9443da5c369Sopenharmony_ci
9453da5c369Sopenharmony_ci    /// If this address represents an abstract socket, return its name.
9463da5c369Sopenharmony_ci    ///
9473da5c369Sopenharmony_ci    /// For abstract sockets only the bare name is returned, without the
9483da5c369Sopenharmony_ci    /// leading NUL byte. `None` is returned for unnamed or path-backed sockets.
9493da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
9503da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
9513da5c369Sopenharmony_ci    pub fn as_abstract(&self) -> Option<&[u8]> {
9523da5c369Sopenharmony_ci        match self.kind() {
9533da5c369Sopenharmony_ci            UnixAddrKind::Abstract(name) => Some(name),
9543da5c369Sopenharmony_ci            _ => None,
9553da5c369Sopenharmony_ci        }
9563da5c369Sopenharmony_ci    }
9573da5c369Sopenharmony_ci
9583da5c369Sopenharmony_ci    /// Check if this address is an "unnamed" unix socket address.
9593da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
9603da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
9613da5c369Sopenharmony_ci    #[inline]
9623da5c369Sopenharmony_ci    pub fn is_unnamed(&self) -> bool {
9633da5c369Sopenharmony_ci        matches!(self.kind(), UnixAddrKind::Unnamed)
9643da5c369Sopenharmony_ci    }
9653da5c369Sopenharmony_ci
9663da5c369Sopenharmony_ci    /// Returns the addrlen of this socket - `offsetof(struct sockaddr_un, sun_path)`
9673da5c369Sopenharmony_ci    #[inline]
9683da5c369Sopenharmony_ci    pub fn path_len(&self) -> usize {
9693da5c369Sopenharmony_ci        self.sun_len() as usize - offset_of!(libc::sockaddr_un, sun_path)
9703da5c369Sopenharmony_ci    }
9713da5c369Sopenharmony_ci    /// Returns a pointer to the raw `sockaddr_un` struct
9723da5c369Sopenharmony_ci    #[inline]
9733da5c369Sopenharmony_ci    pub fn as_ptr(&self) -> *const libc::sockaddr_un {
9743da5c369Sopenharmony_ci        &self.sun
9753da5c369Sopenharmony_ci    }
9763da5c369Sopenharmony_ci    /// Returns a mutable pointer to the raw `sockaddr_un` struct
9773da5c369Sopenharmony_ci    #[inline]
9783da5c369Sopenharmony_ci    pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr_un {
9793da5c369Sopenharmony_ci        &mut self.sun
9803da5c369Sopenharmony_ci    }
9813da5c369Sopenharmony_ci
9823da5c369Sopenharmony_ci    fn sun_len(&self) -> u8 {
9833da5c369Sopenharmony_ci        cfg_if! {
9843da5c369Sopenharmony_ci            if #[cfg(any(target_os = "android",
9853da5c369Sopenharmony_ci                     target_os = "fuchsia",
9863da5c369Sopenharmony_ci                     target_os = "illumos",
9873da5c369Sopenharmony_ci                     target_os = "linux"
9883da5c369Sopenharmony_ci                ))]
9893da5c369Sopenharmony_ci            {
9903da5c369Sopenharmony_ci                self.sun_len
9913da5c369Sopenharmony_ci            } else {
9923da5c369Sopenharmony_ci                self.sun.sun_len
9933da5c369Sopenharmony_ci            }
9943da5c369Sopenharmony_ci        }
9953da5c369Sopenharmony_ci    }
9963da5c369Sopenharmony_ci}
9973da5c369Sopenharmony_ci
9983da5c369Sopenharmony_ciimpl private::SockaddrLikePriv for UnixAddr {}
9993da5c369Sopenharmony_ciimpl SockaddrLike for UnixAddr {
10003da5c369Sopenharmony_ci    #[cfg(any(
10013da5c369Sopenharmony_ci        target_os = "android",
10023da5c369Sopenharmony_ci        target_os = "fuchsia",
10033da5c369Sopenharmony_ci        target_os = "illumos",
10043da5c369Sopenharmony_ci        target_os = "linux"
10053da5c369Sopenharmony_ci    ))]
10063da5c369Sopenharmony_ci    fn len(&self) -> libc::socklen_t {
10073da5c369Sopenharmony_ci        self.sun_len.into()
10083da5c369Sopenharmony_ci    }
10093da5c369Sopenharmony_ci
10103da5c369Sopenharmony_ci    unsafe fn from_raw(
10113da5c369Sopenharmony_ci        addr: *const libc::sockaddr,
10123da5c369Sopenharmony_ci        len: Option<libc::socklen_t>,
10133da5c369Sopenharmony_ci    ) -> Option<Self>
10143da5c369Sopenharmony_ci    where
10153da5c369Sopenharmony_ci        Self: Sized,
10163da5c369Sopenharmony_ci    {
10173da5c369Sopenharmony_ci        if let Some(l) = len {
10183da5c369Sopenharmony_ci            if (l as usize) < offset_of!(libc::sockaddr_un, sun_path)
10193da5c369Sopenharmony_ci                || l > u8::MAX as libc::socklen_t
10203da5c369Sopenharmony_ci            {
10213da5c369Sopenharmony_ci                return None;
10223da5c369Sopenharmony_ci            }
10233da5c369Sopenharmony_ci        }
10243da5c369Sopenharmony_ci        if (*addr).sa_family as i32 != libc::AF_UNIX {
10253da5c369Sopenharmony_ci            return None;
10263da5c369Sopenharmony_ci        }
10273da5c369Sopenharmony_ci        let mut su: libc::sockaddr_un = mem::zeroed();
10283da5c369Sopenharmony_ci        let sup = &mut su as *mut libc::sockaddr_un as *mut u8;
10293da5c369Sopenharmony_ci        cfg_if! {
10303da5c369Sopenharmony_ci            if #[cfg(any(target_os = "android",
10313da5c369Sopenharmony_ci                         target_os = "fuchsia",
10323da5c369Sopenharmony_ci                         target_os = "illumos",
10333da5c369Sopenharmony_ci                         target_os = "linux"
10343da5c369Sopenharmony_ci                ))] {
10353da5c369Sopenharmony_ci                let su_len = len.unwrap_or(
10363da5c369Sopenharmony_ci                    mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
10373da5c369Sopenharmony_ci                );
10383da5c369Sopenharmony_ci            } else {
10393da5c369Sopenharmony_ci                let su_len = len.unwrap_or((*addr).sa_len as libc::socklen_t);
10403da5c369Sopenharmony_ci            }
10413da5c369Sopenharmony_ci        };
10423da5c369Sopenharmony_ci        ptr::copy(addr as *const u8, sup, su_len as usize);
10433da5c369Sopenharmony_ci        Some(Self::from_raw_parts(su, su_len as u8))
10443da5c369Sopenharmony_ci    }
10453da5c369Sopenharmony_ci
10463da5c369Sopenharmony_ci    fn size() -> libc::socklen_t
10473da5c369Sopenharmony_ci    where
10483da5c369Sopenharmony_ci        Self: Sized,
10493da5c369Sopenharmony_ci    {
10503da5c369Sopenharmony_ci        mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
10513da5c369Sopenharmony_ci    }
10523da5c369Sopenharmony_ci}
10533da5c369Sopenharmony_ci
10543da5c369Sopenharmony_ciimpl AsRef<libc::sockaddr_un> for UnixAddr {
10553da5c369Sopenharmony_ci    fn as_ref(&self) -> &libc::sockaddr_un {
10563da5c369Sopenharmony_ci        &self.sun
10573da5c369Sopenharmony_ci    }
10583da5c369Sopenharmony_ci}
10593da5c369Sopenharmony_ci
10603da5c369Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
10613da5c369Sopenharmony_cifn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
10623da5c369Sopenharmony_ci    use fmt::Write;
10633da5c369Sopenharmony_ci    f.write_str("@\"")?;
10643da5c369Sopenharmony_ci    for &b in abs {
10653da5c369Sopenharmony_ci        use fmt::Display;
10663da5c369Sopenharmony_ci        char::from(b).escape_default().fmt(f)?;
10673da5c369Sopenharmony_ci    }
10683da5c369Sopenharmony_ci    f.write_char('"')?;
10693da5c369Sopenharmony_ci    Ok(())
10703da5c369Sopenharmony_ci}
10713da5c369Sopenharmony_ci
10723da5c369Sopenharmony_ciimpl fmt::Display for UnixAddr {
10733da5c369Sopenharmony_ci    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10743da5c369Sopenharmony_ci        match self.kind() {
10753da5c369Sopenharmony_ci            UnixAddrKind::Pathname(path) => path.display().fmt(f),
10763da5c369Sopenharmony_ci            UnixAddrKind::Unnamed => f.pad("<unbound UNIX socket>"),
10773da5c369Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
10783da5c369Sopenharmony_ci            UnixAddrKind::Abstract(name) => fmt_abstract(name, f),
10793da5c369Sopenharmony_ci        }
10803da5c369Sopenharmony_ci    }
10813da5c369Sopenharmony_ci}
10823da5c369Sopenharmony_ci
10833da5c369Sopenharmony_ciimpl PartialEq for UnixAddr {
10843da5c369Sopenharmony_ci    fn eq(&self, other: &UnixAddr) -> bool {
10853da5c369Sopenharmony_ci        self.kind() == other.kind()
10863da5c369Sopenharmony_ci    }
10873da5c369Sopenharmony_ci}
10883da5c369Sopenharmony_ci
10893da5c369Sopenharmony_ciimpl Eq for UnixAddr {}
10903da5c369Sopenharmony_ci
10913da5c369Sopenharmony_ciimpl Hash for UnixAddr {
10923da5c369Sopenharmony_ci    fn hash<H: Hasher>(&self, s: &mut H) {
10933da5c369Sopenharmony_ci        self.kind().hash(s)
10943da5c369Sopenharmony_ci    }
10953da5c369Sopenharmony_ci}
10963da5c369Sopenharmony_ci
10973da5c369Sopenharmony_ci/// Anything that, in C, can be cast back and forth to `sockaddr`.
10983da5c369Sopenharmony_ci///
10993da5c369Sopenharmony_ci/// Most implementors also implement `AsRef<libc::XXX>` to access their
11003da5c369Sopenharmony_ci/// inner type read-only.
11013da5c369Sopenharmony_ci#[allow(clippy::len_without_is_empty)]
11023da5c369Sopenharmony_cipub trait SockaddrLike: private::SockaddrLikePriv {
11033da5c369Sopenharmony_ci    /// Returns a raw pointer to the inner structure.  Useful for FFI.
11043da5c369Sopenharmony_ci    fn as_ptr(&self) -> *const libc::sockaddr {
11053da5c369Sopenharmony_ci        self as *const Self as *const libc::sockaddr
11063da5c369Sopenharmony_ci    }
11073da5c369Sopenharmony_ci
11083da5c369Sopenharmony_ci    /// Unsafe constructor from a variable length source
11093da5c369Sopenharmony_ci    ///
11103da5c369Sopenharmony_ci    /// Some C APIs from provide `len`, and others do not.  If it's provided it
11113da5c369Sopenharmony_ci    /// will be validated.  If not, it will be guessed based on the family.
11123da5c369Sopenharmony_ci    ///
11133da5c369Sopenharmony_ci    /// # Arguments
11143da5c369Sopenharmony_ci    ///
11153da5c369Sopenharmony_ci    /// - `addr`:   raw pointer to something that can be cast to a
11163da5c369Sopenharmony_ci    ///             `libc::sockaddr`. For example, `libc::sockaddr_in`,
11173da5c369Sopenharmony_ci    ///             `libc::sockaddr_in6`, etc.
11183da5c369Sopenharmony_ci    /// - `len`:    For fixed-width types like `sockaddr_in`, it will be
11193da5c369Sopenharmony_ci    ///             validated if present and ignored if not.  For variable-width
11203da5c369Sopenharmony_ci    ///             types it is required and must be the total length of valid
11213da5c369Sopenharmony_ci    ///             data.  For example, if `addr` points to a
11223da5c369Sopenharmony_ci    ///             named `sockaddr_un`, then `len` must be the length of the
11233da5c369Sopenharmony_ci    ///             structure up to but not including the trailing NUL.
11243da5c369Sopenharmony_ci    ///
11253da5c369Sopenharmony_ci    /// # Safety
11263da5c369Sopenharmony_ci    ///
11273da5c369Sopenharmony_ci    /// `addr` must be valid for the specific type of sockaddr.  `len`, if
11283da5c369Sopenharmony_ci    /// present, must not exceed the length of valid data in `addr`.
11293da5c369Sopenharmony_ci    unsafe fn from_raw(
11303da5c369Sopenharmony_ci        addr: *const libc::sockaddr,
11313da5c369Sopenharmony_ci        len: Option<libc::socklen_t>,
11323da5c369Sopenharmony_ci    ) -> Option<Self>
11333da5c369Sopenharmony_ci    where
11343da5c369Sopenharmony_ci        Self: Sized;
11353da5c369Sopenharmony_ci
11363da5c369Sopenharmony_ci    /// Return the address family of this socket
11373da5c369Sopenharmony_ci    ///
11383da5c369Sopenharmony_ci    /// # Examples
11393da5c369Sopenharmony_ci    /// One common use is to match on the family of a union type, like this:
11403da5c369Sopenharmony_ci    /// ```
11413da5c369Sopenharmony_ci    /// # use nix::sys::socket::*;
11423da5c369Sopenharmony_ci    /// let fd = socket(AddressFamily::Inet, SockType::Stream,
11433da5c369Sopenharmony_ci    ///     SockFlag::empty(), None).unwrap();
11443da5c369Sopenharmony_ci    /// let ss: SockaddrStorage = getsockname(fd).unwrap();
11453da5c369Sopenharmony_ci    /// match ss.family().unwrap() {
11463da5c369Sopenharmony_ci    ///     AddressFamily::Inet => println!("{}", ss.as_sockaddr_in().unwrap()),
11473da5c369Sopenharmony_ci    ///     AddressFamily::Inet6 => println!("{}", ss.as_sockaddr_in6().unwrap()),
11483da5c369Sopenharmony_ci    ///     _ => println!("Unexpected address family")
11493da5c369Sopenharmony_ci    /// }
11503da5c369Sopenharmony_ci    /// ```
11513da5c369Sopenharmony_ci    fn family(&self) -> Option<AddressFamily> {
11523da5c369Sopenharmony_ci        // Safe since all implementors have a sa_family field at the same
11533da5c369Sopenharmony_ci        // address, and they're all repr(C)
11543da5c369Sopenharmony_ci        AddressFamily::from_i32(unsafe {
11553da5c369Sopenharmony_ci            (*(self as *const Self as *const libc::sockaddr)).sa_family as i32
11563da5c369Sopenharmony_ci        })
11573da5c369Sopenharmony_ci    }
11583da5c369Sopenharmony_ci
11593da5c369Sopenharmony_ci    cfg_if! {
11603da5c369Sopenharmony_ci        if #[cfg(any(target_os = "dragonfly",
11613da5c369Sopenharmony_ci                  target_os = "freebsd",
11623da5c369Sopenharmony_ci                  target_os = "ios",
11633da5c369Sopenharmony_ci                  target_os = "macos",
11643da5c369Sopenharmony_ci                  target_os = "netbsd",
11653da5c369Sopenharmony_ci                  target_os = "openbsd"))] {
11663da5c369Sopenharmony_ci            /// Return the length of valid data in the sockaddr structure.
11673da5c369Sopenharmony_ci            ///
11683da5c369Sopenharmony_ci            /// For fixed-size sockaddrs, this should be the size of the
11693da5c369Sopenharmony_ci            /// structure.  But for variable-sized types like [`UnixAddr`] it
11703da5c369Sopenharmony_ci            /// may be less.
11713da5c369Sopenharmony_ci            fn len(&self) -> libc::socklen_t {
11723da5c369Sopenharmony_ci                // Safe since all implementors have a sa_len field at the same
11733da5c369Sopenharmony_ci                // address, and they're all repr(transparent).
11743da5c369Sopenharmony_ci                // Robust for all implementors.
11753da5c369Sopenharmony_ci                unsafe {
11763da5c369Sopenharmony_ci                    (*(self as *const Self as *const libc::sockaddr)).sa_len
11773da5c369Sopenharmony_ci                }.into()
11783da5c369Sopenharmony_ci            }
11793da5c369Sopenharmony_ci        } else {
11803da5c369Sopenharmony_ci            /// Return the length of valid data in the sockaddr structure.
11813da5c369Sopenharmony_ci            ///
11823da5c369Sopenharmony_ci            /// For fixed-size sockaddrs, this should be the size of the
11833da5c369Sopenharmony_ci            /// structure.  But for variable-sized types like [`UnixAddr`] it
11843da5c369Sopenharmony_ci            /// may be less.
11853da5c369Sopenharmony_ci            fn len(&self) -> libc::socklen_t {
11863da5c369Sopenharmony_ci                // No robust default implementation is possible without an
11873da5c369Sopenharmony_ci                // sa_len field.  Implementors with a variable size must
11883da5c369Sopenharmony_ci                // override this method.
11893da5c369Sopenharmony_ci                mem::size_of_val(self) as libc::socklen_t
11903da5c369Sopenharmony_ci            }
11913da5c369Sopenharmony_ci        }
11923da5c369Sopenharmony_ci    }
11933da5c369Sopenharmony_ci
11943da5c369Sopenharmony_ci    /// Return the available space in the structure
11953da5c369Sopenharmony_ci    fn size() -> libc::socklen_t
11963da5c369Sopenharmony_ci    where
11973da5c369Sopenharmony_ci        Self: Sized,
11983da5c369Sopenharmony_ci    {
11993da5c369Sopenharmony_ci        mem::size_of::<Self>() as libc::socklen_t
12003da5c369Sopenharmony_ci    }
12013da5c369Sopenharmony_ci}
12023da5c369Sopenharmony_ci
12033da5c369Sopenharmony_ciimpl private::SockaddrLikePriv for () {
12043da5c369Sopenharmony_ci    fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
12053da5c369Sopenharmony_ci        ptr::null_mut()
12063da5c369Sopenharmony_ci    }
12073da5c369Sopenharmony_ci}
12083da5c369Sopenharmony_ci
12093da5c369Sopenharmony_ci/// `()` can be used in place of a real Sockaddr when no address is expected,
12103da5c369Sopenharmony_ci/// for example for a field of `Option<S> where S: SockaddrLike`.
12113da5c369Sopenharmony_ci// If this RFC ever stabilizes, then ! will be a better choice.
12123da5c369Sopenharmony_ci// https://github.com/rust-lang/rust/issues/35121
12133da5c369Sopenharmony_ciimpl SockaddrLike for () {
12143da5c369Sopenharmony_ci    fn as_ptr(&self) -> *const libc::sockaddr {
12153da5c369Sopenharmony_ci        ptr::null()
12163da5c369Sopenharmony_ci    }
12173da5c369Sopenharmony_ci
12183da5c369Sopenharmony_ci    unsafe fn from_raw(
12193da5c369Sopenharmony_ci        _: *const libc::sockaddr,
12203da5c369Sopenharmony_ci        _: Option<libc::socklen_t>,
12213da5c369Sopenharmony_ci    ) -> Option<Self>
12223da5c369Sopenharmony_ci    where
12233da5c369Sopenharmony_ci        Self: Sized,
12243da5c369Sopenharmony_ci    {
12253da5c369Sopenharmony_ci        None
12263da5c369Sopenharmony_ci    }
12273da5c369Sopenharmony_ci
12283da5c369Sopenharmony_ci    fn family(&self) -> Option<AddressFamily> {
12293da5c369Sopenharmony_ci        None
12303da5c369Sopenharmony_ci    }
12313da5c369Sopenharmony_ci
12323da5c369Sopenharmony_ci    fn len(&self) -> libc::socklen_t {
12333da5c369Sopenharmony_ci        0
12343da5c369Sopenharmony_ci    }
12353da5c369Sopenharmony_ci}
12363da5c369Sopenharmony_ci
12373da5c369Sopenharmony_ci/// An IPv4 socket address
12383da5c369Sopenharmony_ci// This is identical to net::SocketAddrV4.  But the standard library
12393da5c369Sopenharmony_ci// doesn't allow direct access to the libc fields, which we need.  So we
12403da5c369Sopenharmony_ci// reimplement it here.
12413da5c369Sopenharmony_ci#[cfg(feature = "net")]
12423da5c369Sopenharmony_ci#[repr(transparent)]
12433da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
12443da5c369Sopenharmony_cipub struct SockaddrIn(libc::sockaddr_in);
12453da5c369Sopenharmony_ci
12463da5c369Sopenharmony_ci#[cfg(feature = "net")]
12473da5c369Sopenharmony_ciimpl SockaddrIn {
12483da5c369Sopenharmony_ci    /// Returns the IP address associated with this socket address, in native
12493da5c369Sopenharmony_ci    /// endian.
12503da5c369Sopenharmony_ci    pub const fn ip(&self) -> libc::in_addr_t {
12513da5c369Sopenharmony_ci        u32::from_be(self.0.sin_addr.s_addr)
12523da5c369Sopenharmony_ci    }
12533da5c369Sopenharmony_ci
12543da5c369Sopenharmony_ci    /// Creates a new socket address from IPv4 octets and a port number.
12553da5c369Sopenharmony_ci    pub fn new(a: u8, b: u8, c: u8, d: u8, port: u16) -> Self {
12563da5c369Sopenharmony_ci        Self(libc::sockaddr_in {
12573da5c369Sopenharmony_ci            #[cfg(any(
12583da5c369Sopenharmony_ci                target_os = "dragonfly",
12593da5c369Sopenharmony_ci                target_os = "freebsd",
12603da5c369Sopenharmony_ci                target_os = "ios",
12613da5c369Sopenharmony_ci                target_os = "macos",
12623da5c369Sopenharmony_ci                target_os = "netbsd",
12633da5c369Sopenharmony_ci                target_os = "haiku",
12643da5c369Sopenharmony_ci                target_os = "openbsd"
12653da5c369Sopenharmony_ci            ))]
12663da5c369Sopenharmony_ci            sin_len: Self::size() as u8,
12673da5c369Sopenharmony_ci            sin_family: AddressFamily::Inet as sa_family_t,
12683da5c369Sopenharmony_ci            sin_port: u16::to_be(port),
12693da5c369Sopenharmony_ci            sin_addr: libc::in_addr {
12703da5c369Sopenharmony_ci                s_addr: u32::from_ne_bytes([a, b, c, d]),
12713da5c369Sopenharmony_ci            },
12723da5c369Sopenharmony_ci            sin_zero: unsafe { mem::zeroed() },
12733da5c369Sopenharmony_ci        })
12743da5c369Sopenharmony_ci    }
12753da5c369Sopenharmony_ci
12763da5c369Sopenharmony_ci    /// Returns the port number associated with this socket address, in native
12773da5c369Sopenharmony_ci    /// endian.
12783da5c369Sopenharmony_ci    pub const fn port(&self) -> u16 {
12793da5c369Sopenharmony_ci        u16::from_be(self.0.sin_port)
12803da5c369Sopenharmony_ci    }
12813da5c369Sopenharmony_ci}
12823da5c369Sopenharmony_ci
12833da5c369Sopenharmony_ci#[cfg(feature = "net")]
12843da5c369Sopenharmony_ciimpl private::SockaddrLikePriv for SockaddrIn {}
12853da5c369Sopenharmony_ci#[cfg(feature = "net")]
12863da5c369Sopenharmony_ciimpl SockaddrLike for SockaddrIn {
12873da5c369Sopenharmony_ci    unsafe fn from_raw(
12883da5c369Sopenharmony_ci        addr: *const libc::sockaddr,
12893da5c369Sopenharmony_ci        len: Option<libc::socklen_t>,
12903da5c369Sopenharmony_ci    ) -> Option<Self>
12913da5c369Sopenharmony_ci    where
12923da5c369Sopenharmony_ci        Self: Sized,
12933da5c369Sopenharmony_ci    {
12943da5c369Sopenharmony_ci        if let Some(l) = len {
12953da5c369Sopenharmony_ci            if l != mem::size_of::<libc::sockaddr_in>() as libc::socklen_t {
12963da5c369Sopenharmony_ci                return None;
12973da5c369Sopenharmony_ci            }
12983da5c369Sopenharmony_ci        }
12993da5c369Sopenharmony_ci        if (*addr).sa_family as i32 != libc::AF_INET {
13003da5c369Sopenharmony_ci            return None;
13013da5c369Sopenharmony_ci        }
13023da5c369Sopenharmony_ci        Some(Self(ptr::read_unaligned(addr as *const _)))
13033da5c369Sopenharmony_ci    }
13043da5c369Sopenharmony_ci}
13053da5c369Sopenharmony_ci
13063da5c369Sopenharmony_ci#[cfg(feature = "net")]
13073da5c369Sopenharmony_ciimpl AsRef<libc::sockaddr_in> for SockaddrIn {
13083da5c369Sopenharmony_ci    fn as_ref(&self) -> &libc::sockaddr_in {
13093da5c369Sopenharmony_ci        &self.0
13103da5c369Sopenharmony_ci    }
13113da5c369Sopenharmony_ci}
13123da5c369Sopenharmony_ci
13133da5c369Sopenharmony_ci#[cfg(feature = "net")]
13143da5c369Sopenharmony_ciimpl fmt::Display for SockaddrIn {
13153da5c369Sopenharmony_ci    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
13163da5c369Sopenharmony_ci        let ne = u32::from_be(self.0.sin_addr.s_addr);
13173da5c369Sopenharmony_ci        let port = u16::from_be(self.0.sin_port);
13183da5c369Sopenharmony_ci        write!(
13193da5c369Sopenharmony_ci            f,
13203da5c369Sopenharmony_ci            "{}.{}.{}.{}:{}",
13213da5c369Sopenharmony_ci            ne >> 24,
13223da5c369Sopenharmony_ci            (ne >> 16) & 0xFF,
13233da5c369Sopenharmony_ci            (ne >> 8) & 0xFF,
13243da5c369Sopenharmony_ci            ne & 0xFF,
13253da5c369Sopenharmony_ci            port
13263da5c369Sopenharmony_ci        )
13273da5c369Sopenharmony_ci    }
13283da5c369Sopenharmony_ci}
13293da5c369Sopenharmony_ci
13303da5c369Sopenharmony_ci#[cfg(feature = "net")]
13313da5c369Sopenharmony_ciimpl From<net::SocketAddrV4> for SockaddrIn {
13323da5c369Sopenharmony_ci    fn from(addr: net::SocketAddrV4) -> Self {
13333da5c369Sopenharmony_ci        Self(libc::sockaddr_in {
13343da5c369Sopenharmony_ci            #[cfg(any(
13353da5c369Sopenharmony_ci                target_os = "dragonfly",
13363da5c369Sopenharmony_ci                target_os = "freebsd",
13373da5c369Sopenharmony_ci                target_os = "haiku",
13383da5c369Sopenharmony_ci                target_os = "hermit",
13393da5c369Sopenharmony_ci                target_os = "ios",
13403da5c369Sopenharmony_ci                target_os = "macos",
13413da5c369Sopenharmony_ci                target_os = "netbsd",
13423da5c369Sopenharmony_ci                target_os = "openbsd"
13433da5c369Sopenharmony_ci            ))]
13443da5c369Sopenharmony_ci            sin_len: mem::size_of::<libc::sockaddr_in>() as u8,
13453da5c369Sopenharmony_ci            sin_family: AddressFamily::Inet as sa_family_t,
13463da5c369Sopenharmony_ci            sin_port: addr.port().to_be(), // network byte order
13473da5c369Sopenharmony_ci            sin_addr: ipv4addr_to_libc(*addr.ip()),
13483da5c369Sopenharmony_ci            ..unsafe { mem::zeroed() }
13493da5c369Sopenharmony_ci        })
13503da5c369Sopenharmony_ci    }
13513da5c369Sopenharmony_ci}
13523da5c369Sopenharmony_ci
13533da5c369Sopenharmony_ci#[cfg(feature = "net")]
13543da5c369Sopenharmony_ciimpl From<SockaddrIn> for net::SocketAddrV4 {
13553da5c369Sopenharmony_ci    fn from(addr: SockaddrIn) -> Self {
13563da5c369Sopenharmony_ci        net::SocketAddrV4::new(
13573da5c369Sopenharmony_ci            net::Ipv4Addr::from(addr.0.sin_addr.s_addr.to_ne_bytes()),
13583da5c369Sopenharmony_ci            u16::from_be(addr.0.sin_port),
13593da5c369Sopenharmony_ci        )
13603da5c369Sopenharmony_ci    }
13613da5c369Sopenharmony_ci}
13623da5c369Sopenharmony_ci
13633da5c369Sopenharmony_ci#[cfg(feature = "net")]
13643da5c369Sopenharmony_ciimpl std::str::FromStr for SockaddrIn {
13653da5c369Sopenharmony_ci    type Err = net::AddrParseError;
13663da5c369Sopenharmony_ci
13673da5c369Sopenharmony_ci    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
13683da5c369Sopenharmony_ci        net::SocketAddrV4::from_str(s).map(SockaddrIn::from)
13693da5c369Sopenharmony_ci    }
13703da5c369Sopenharmony_ci}
13713da5c369Sopenharmony_ci
13723da5c369Sopenharmony_ci/// An IPv6 socket address
13733da5c369Sopenharmony_ci#[cfg(feature = "net")]
13743da5c369Sopenharmony_ci#[repr(transparent)]
13753da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
13763da5c369Sopenharmony_cipub struct SockaddrIn6(libc::sockaddr_in6);
13773da5c369Sopenharmony_ci
13783da5c369Sopenharmony_ci#[cfg(feature = "net")]
13793da5c369Sopenharmony_ciimpl SockaddrIn6 {
13803da5c369Sopenharmony_ci    /// Returns the flow information associated with this address.
13813da5c369Sopenharmony_ci    pub const fn flowinfo(&self) -> u32 {
13823da5c369Sopenharmony_ci        self.0.sin6_flowinfo
13833da5c369Sopenharmony_ci    }
13843da5c369Sopenharmony_ci
13853da5c369Sopenharmony_ci    /// Returns the IP address associated with this socket address.
13863da5c369Sopenharmony_ci    pub fn ip(&self) -> net::Ipv6Addr {
13873da5c369Sopenharmony_ci        net::Ipv6Addr::from(self.0.sin6_addr.s6_addr)
13883da5c369Sopenharmony_ci    }
13893da5c369Sopenharmony_ci
13903da5c369Sopenharmony_ci    /// Returns the port number associated with this socket address, in native
13913da5c369Sopenharmony_ci    /// endian.
13923da5c369Sopenharmony_ci    pub const fn port(&self) -> u16 {
13933da5c369Sopenharmony_ci        u16::from_be(self.0.sin6_port)
13943da5c369Sopenharmony_ci    }
13953da5c369Sopenharmony_ci
13963da5c369Sopenharmony_ci    /// Returns the scope ID associated with this address.
13973da5c369Sopenharmony_ci    pub const fn scope_id(&self) -> u32 {
13983da5c369Sopenharmony_ci        self.0.sin6_scope_id
13993da5c369Sopenharmony_ci    }
14003da5c369Sopenharmony_ci}
14013da5c369Sopenharmony_ci
14023da5c369Sopenharmony_ci#[cfg(feature = "net")]
14033da5c369Sopenharmony_ciimpl private::SockaddrLikePriv for SockaddrIn6 {}
14043da5c369Sopenharmony_ci#[cfg(feature = "net")]
14053da5c369Sopenharmony_ciimpl SockaddrLike for SockaddrIn6 {
14063da5c369Sopenharmony_ci    unsafe fn from_raw(
14073da5c369Sopenharmony_ci        addr: *const libc::sockaddr,
14083da5c369Sopenharmony_ci        len: Option<libc::socklen_t>,
14093da5c369Sopenharmony_ci    ) -> Option<Self>
14103da5c369Sopenharmony_ci    where
14113da5c369Sopenharmony_ci        Self: Sized,
14123da5c369Sopenharmony_ci    {
14133da5c369Sopenharmony_ci        if let Some(l) = len {
14143da5c369Sopenharmony_ci            if l != mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t {
14153da5c369Sopenharmony_ci                return None;
14163da5c369Sopenharmony_ci            }
14173da5c369Sopenharmony_ci        }
14183da5c369Sopenharmony_ci        if (*addr).sa_family as i32 != libc::AF_INET6 {
14193da5c369Sopenharmony_ci            return None;
14203da5c369Sopenharmony_ci        }
14213da5c369Sopenharmony_ci        Some(Self(ptr::read_unaligned(addr as *const _)))
14223da5c369Sopenharmony_ci    }
14233da5c369Sopenharmony_ci}
14243da5c369Sopenharmony_ci
14253da5c369Sopenharmony_ci#[cfg(feature = "net")]
14263da5c369Sopenharmony_ciimpl AsRef<libc::sockaddr_in6> for SockaddrIn6 {
14273da5c369Sopenharmony_ci    fn as_ref(&self) -> &libc::sockaddr_in6 {
14283da5c369Sopenharmony_ci        &self.0
14293da5c369Sopenharmony_ci    }
14303da5c369Sopenharmony_ci}
14313da5c369Sopenharmony_ci
14323da5c369Sopenharmony_ci#[cfg(feature = "net")]
14333da5c369Sopenharmony_ciimpl fmt::Display for SockaddrIn6 {
14343da5c369Sopenharmony_ci    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
14353da5c369Sopenharmony_ci        // These things are really hard to display properly.  Easier to let std
14363da5c369Sopenharmony_ci        // do it.
14373da5c369Sopenharmony_ci        let std = net::SocketAddrV6::new(
14383da5c369Sopenharmony_ci            self.ip(),
14393da5c369Sopenharmony_ci            self.port(),
14403da5c369Sopenharmony_ci            self.flowinfo(),
14413da5c369Sopenharmony_ci            self.scope_id(),
14423da5c369Sopenharmony_ci        );
14433da5c369Sopenharmony_ci        std.fmt(f)
14443da5c369Sopenharmony_ci    }
14453da5c369Sopenharmony_ci}
14463da5c369Sopenharmony_ci
14473da5c369Sopenharmony_ci#[cfg(feature = "net")]
14483da5c369Sopenharmony_ciimpl From<net::SocketAddrV6> for SockaddrIn6 {
14493da5c369Sopenharmony_ci    fn from(addr: net::SocketAddrV6) -> Self {
14503da5c369Sopenharmony_ci        #[allow(clippy::needless_update)] // It isn't needless on Illumos
14513da5c369Sopenharmony_ci        Self(libc::sockaddr_in6 {
14523da5c369Sopenharmony_ci            #[cfg(any(
14533da5c369Sopenharmony_ci                target_os = "dragonfly",
14543da5c369Sopenharmony_ci                target_os = "freebsd",
14553da5c369Sopenharmony_ci                target_os = "haiku",
14563da5c369Sopenharmony_ci                target_os = "hermit",
14573da5c369Sopenharmony_ci                target_os = "ios",
14583da5c369Sopenharmony_ci                target_os = "macos",
14593da5c369Sopenharmony_ci                target_os = "netbsd",
14603da5c369Sopenharmony_ci                target_os = "openbsd"
14613da5c369Sopenharmony_ci            ))]
14623da5c369Sopenharmony_ci            sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8,
14633da5c369Sopenharmony_ci            sin6_family: AddressFamily::Inet6 as sa_family_t,
14643da5c369Sopenharmony_ci            sin6_port: addr.port().to_be(), // network byte order
14653da5c369Sopenharmony_ci            sin6_addr: ipv6addr_to_libc(addr.ip()),
14663da5c369Sopenharmony_ci            sin6_flowinfo: addr.flowinfo(), // host byte order
14673da5c369Sopenharmony_ci            sin6_scope_id: addr.scope_id(), // host byte order
14683da5c369Sopenharmony_ci            ..unsafe { mem::zeroed() }
14693da5c369Sopenharmony_ci        })
14703da5c369Sopenharmony_ci    }
14713da5c369Sopenharmony_ci}
14723da5c369Sopenharmony_ci
14733da5c369Sopenharmony_ci#[cfg(feature = "net")]
14743da5c369Sopenharmony_ciimpl From<SockaddrIn6> for net::SocketAddrV6 {
14753da5c369Sopenharmony_ci    fn from(addr: SockaddrIn6) -> Self {
14763da5c369Sopenharmony_ci        net::SocketAddrV6::new(
14773da5c369Sopenharmony_ci            net::Ipv6Addr::from(addr.0.sin6_addr.s6_addr),
14783da5c369Sopenharmony_ci            u16::from_be(addr.0.sin6_port),
14793da5c369Sopenharmony_ci            addr.0.sin6_flowinfo,
14803da5c369Sopenharmony_ci            addr.0.sin6_scope_id,
14813da5c369Sopenharmony_ci        )
14823da5c369Sopenharmony_ci    }
14833da5c369Sopenharmony_ci}
14843da5c369Sopenharmony_ci
14853da5c369Sopenharmony_ci#[cfg(feature = "net")]
14863da5c369Sopenharmony_ciimpl std::str::FromStr for SockaddrIn6 {
14873da5c369Sopenharmony_ci    type Err = net::AddrParseError;
14883da5c369Sopenharmony_ci
14893da5c369Sopenharmony_ci    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
14903da5c369Sopenharmony_ci        net::SocketAddrV6::from_str(s).map(SockaddrIn6::from)
14913da5c369Sopenharmony_ci    }
14923da5c369Sopenharmony_ci}
14933da5c369Sopenharmony_ci
14943da5c369Sopenharmony_ci/// A container for any sockaddr type
14953da5c369Sopenharmony_ci///
14963da5c369Sopenharmony_ci/// Just like C's `sockaddr_storage`, this type is large enough to hold any type
14973da5c369Sopenharmony_ci/// of sockaddr.  It can be used as an argument with functions like
14983da5c369Sopenharmony_ci/// [`bind`](super::bind) and [`getsockname`](super::getsockname).  Though it is
14993da5c369Sopenharmony_ci/// a union, it can be safely accessed through the `as_*` methods.
15003da5c369Sopenharmony_ci///
15013da5c369Sopenharmony_ci/// # Example
15023da5c369Sopenharmony_ci/// ```
15033da5c369Sopenharmony_ci/// # use nix::sys::socket::*;
15043da5c369Sopenharmony_ci/// # use std::str::FromStr;
15053da5c369Sopenharmony_ci/// let localhost = SockaddrIn::from_str("127.0.0.1:8081").unwrap();
15063da5c369Sopenharmony_ci/// let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(),
15073da5c369Sopenharmony_ci///     None).unwrap();
15083da5c369Sopenharmony_ci/// bind(fd, &localhost).expect("bind");
15093da5c369Sopenharmony_ci/// let ss: SockaddrStorage = getsockname(fd).expect("getsockname");
15103da5c369Sopenharmony_ci/// assert_eq!(&localhost, ss.as_sockaddr_in().unwrap());
15113da5c369Sopenharmony_ci/// ```
15123da5c369Sopenharmony_ci#[derive(Clone, Copy, Eq)]
15133da5c369Sopenharmony_ci#[repr(C)]
15143da5c369Sopenharmony_cipub union SockaddrStorage {
15153da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
15163da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
15173da5c369Sopenharmony_ci    alg: AlgAddr,
15183da5c369Sopenharmony_ci    #[cfg(feature = "net")]
15193da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
15203da5c369Sopenharmony_ci    dl: LinkAddr,
15213da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
15223da5c369Sopenharmony_ci    nl: NetlinkAddr,
15233da5c369Sopenharmony_ci    #[cfg(all(
15243da5c369Sopenharmony_ci        feature = "ioctl",
15253da5c369Sopenharmony_ci        any(target_os = "ios", target_os = "macos")
15263da5c369Sopenharmony_ci    ))]
15273da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
15283da5c369Sopenharmony_ci    sctl: SysControlAddr,
15293da5c369Sopenharmony_ci    #[cfg(feature = "net")]
15303da5c369Sopenharmony_ci    sin: SockaddrIn,
15313da5c369Sopenharmony_ci    #[cfg(feature = "net")]
15323da5c369Sopenharmony_ci    sin6: SockaddrIn6,
15333da5c369Sopenharmony_ci    ss: libc::sockaddr_storage,
15343da5c369Sopenharmony_ci    su: UnixAddr,
15353da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
15363da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
15373da5c369Sopenharmony_ci    vsock: VsockAddr,
15383da5c369Sopenharmony_ci}
15393da5c369Sopenharmony_ciimpl private::SockaddrLikePriv for SockaddrStorage {}
15403da5c369Sopenharmony_ciimpl SockaddrLike for SockaddrStorage {
15413da5c369Sopenharmony_ci    unsafe fn from_raw(
15423da5c369Sopenharmony_ci        addr: *const libc::sockaddr,
15433da5c369Sopenharmony_ci        l: Option<libc::socklen_t>,
15443da5c369Sopenharmony_ci    ) -> Option<Self>
15453da5c369Sopenharmony_ci    where
15463da5c369Sopenharmony_ci        Self: Sized,
15473da5c369Sopenharmony_ci    {
15483da5c369Sopenharmony_ci        if addr.is_null() {
15493da5c369Sopenharmony_ci            return None;
15503da5c369Sopenharmony_ci        }
15513da5c369Sopenharmony_ci        if let Some(len) = l {
15523da5c369Sopenharmony_ci            let ulen = len as usize;
15533da5c369Sopenharmony_ci            if ulen < offset_of!(libc::sockaddr, sa_data)
15543da5c369Sopenharmony_ci                || ulen > mem::size_of::<libc::sockaddr_storage>()
15553da5c369Sopenharmony_ci            {
15563da5c369Sopenharmony_ci                None
15573da5c369Sopenharmony_ci            } else {
15583da5c369Sopenharmony_ci                let mut ss: libc::sockaddr_storage = mem::zeroed();
15593da5c369Sopenharmony_ci                let ssp = &mut ss as *mut libc::sockaddr_storage as *mut u8;
15603da5c369Sopenharmony_ci                ptr::copy(addr as *const u8, ssp, len as usize);
15613da5c369Sopenharmony_ci                #[cfg(any(
15623da5c369Sopenharmony_ci                    target_os = "android",
15633da5c369Sopenharmony_ci                    target_os = "fuchsia",
15643da5c369Sopenharmony_ci                    target_os = "illumos",
15653da5c369Sopenharmony_ci                    target_os = "linux"
15663da5c369Sopenharmony_ci                ))]
15673da5c369Sopenharmony_ci                if i32::from(ss.ss_family) == libc::AF_UNIX {
15683da5c369Sopenharmony_ci                    // Safe because we UnixAddr is strictly smaller than
15693da5c369Sopenharmony_ci                    // SockaddrStorage, and we just initialized the structure.
15703da5c369Sopenharmony_ci                    (*(&mut ss as *mut libc::sockaddr_storage as *mut UnixAddr)).sun_len = len as u8;
15713da5c369Sopenharmony_ci                }
15723da5c369Sopenharmony_ci                Some(Self { ss })
15733da5c369Sopenharmony_ci            }
15743da5c369Sopenharmony_ci        } else {
15753da5c369Sopenharmony_ci            // If length is not available and addr is of a fixed-length type,
15763da5c369Sopenharmony_ci            // copy it.  If addr is of a variable length type and len is not
15773da5c369Sopenharmony_ci            // available, then there's nothing we can do.
15783da5c369Sopenharmony_ci            match (*addr).sa_family as i32 {
15793da5c369Sopenharmony_ci                #[cfg(any(target_os = "android", target_os = "linux"))]
15803da5c369Sopenharmony_ci                libc::AF_ALG => {
15813da5c369Sopenharmony_ci                    AlgAddr::from_raw(addr, l).map(|alg| Self { alg })
15823da5c369Sopenharmony_ci                }
15833da5c369Sopenharmony_ci                #[cfg(feature = "net")]
15843da5c369Sopenharmony_ci                libc::AF_INET => {
15853da5c369Sopenharmony_ci                    SockaddrIn::from_raw(addr, l).map(|sin| Self { sin })
15863da5c369Sopenharmony_ci                }
15873da5c369Sopenharmony_ci                #[cfg(feature = "net")]
15883da5c369Sopenharmony_ci                libc::AF_INET6 => {
15893da5c369Sopenharmony_ci                    SockaddrIn6::from_raw(addr, l).map(|sin6| Self { sin6 })
15903da5c369Sopenharmony_ci                }
15913da5c369Sopenharmony_ci                #[cfg(any(
15923da5c369Sopenharmony_ci                    target_os = "dragonfly",
15933da5c369Sopenharmony_ci                    target_os = "freebsd",
15943da5c369Sopenharmony_ci                    target_os = "ios",
15953da5c369Sopenharmony_ci                    target_os = "macos",
15963da5c369Sopenharmony_ci                    target_os = "illumos",
15973da5c369Sopenharmony_ci                    target_os = "netbsd",
15983da5c369Sopenharmony_ci                    target_os = "haiku",
15993da5c369Sopenharmony_ci                    target_os = "openbsd"
16003da5c369Sopenharmony_ci                ))]
16013da5c369Sopenharmony_ci                #[cfg(feature = "net")]
16023da5c369Sopenharmony_ci                libc::AF_LINK => {
16033da5c369Sopenharmony_ci                    LinkAddr::from_raw(addr, l).map(|dl| Self { dl })
16043da5c369Sopenharmony_ci                }
16053da5c369Sopenharmony_ci                #[cfg(any(target_os = "android", target_os = "linux"))]
16063da5c369Sopenharmony_ci                libc::AF_NETLINK => {
16073da5c369Sopenharmony_ci                    NetlinkAddr::from_raw(addr, l).map(|nl| Self { nl })
16083da5c369Sopenharmony_ci                }
16093da5c369Sopenharmony_ci                #[cfg(any(
16103da5c369Sopenharmony_ci                    target_os = "android",
16113da5c369Sopenharmony_ci                    target_os = "fuchsia",
16123da5c369Sopenharmony_ci                    target_os = "linux"
16133da5c369Sopenharmony_ci                ))]
16143da5c369Sopenharmony_ci                #[cfg(feature = "net")]
16153da5c369Sopenharmony_ci                libc::AF_PACKET => {
16163da5c369Sopenharmony_ci                    LinkAddr::from_raw(addr, l).map(|dl| Self { dl })
16173da5c369Sopenharmony_ci                }
16183da5c369Sopenharmony_ci                #[cfg(all(
16193da5c369Sopenharmony_ci                    feature = "ioctl",
16203da5c369Sopenharmony_ci                    any(target_os = "ios", target_os = "macos")
16213da5c369Sopenharmony_ci                ))]
16223da5c369Sopenharmony_ci                libc::AF_SYSTEM => {
16233da5c369Sopenharmony_ci                    SysControlAddr::from_raw(addr, l).map(|sctl| Self { sctl })
16243da5c369Sopenharmony_ci                }
16253da5c369Sopenharmony_ci                #[cfg(any(target_os = "android", target_os = "linux"))]
16263da5c369Sopenharmony_ci                libc::AF_VSOCK => {
16273da5c369Sopenharmony_ci                    VsockAddr::from_raw(addr, l).map(|vsock| Self { vsock })
16283da5c369Sopenharmony_ci                }
16293da5c369Sopenharmony_ci                _ => None,
16303da5c369Sopenharmony_ci            }
16313da5c369Sopenharmony_ci        }
16323da5c369Sopenharmony_ci    }
16333da5c369Sopenharmony_ci
16343da5c369Sopenharmony_ci    #[cfg(any(
16353da5c369Sopenharmony_ci        target_os = "android",
16363da5c369Sopenharmony_ci        target_os = "fuchsia",
16373da5c369Sopenharmony_ci        target_os = "illumos",
16383da5c369Sopenharmony_ci        target_os = "linux"
16393da5c369Sopenharmony_ci    ))]
16403da5c369Sopenharmony_ci    fn len(&self) -> libc::socklen_t {
16413da5c369Sopenharmony_ci        match self.as_unix_addr() {
16423da5c369Sopenharmony_ci            // The UnixAddr type knows its own length
16433da5c369Sopenharmony_ci            Some(ua) => ua.len(),
16443da5c369Sopenharmony_ci            // For all else, we're just a boring SockaddrStorage
16453da5c369Sopenharmony_ci            None => mem::size_of_val(self) as libc::socklen_t
16463da5c369Sopenharmony_ci        }
16473da5c369Sopenharmony_ci    }
16483da5c369Sopenharmony_ci}
16493da5c369Sopenharmony_ci
16503da5c369Sopenharmony_cimacro_rules! accessors {
16513da5c369Sopenharmony_ci    (
16523da5c369Sopenharmony_ci        $fname:ident,
16533da5c369Sopenharmony_ci        $fname_mut:ident,
16543da5c369Sopenharmony_ci        $sockty:ty,
16553da5c369Sopenharmony_ci        $family:expr,
16563da5c369Sopenharmony_ci        $libc_ty:ty,
16573da5c369Sopenharmony_ci        $field:ident) => {
16583da5c369Sopenharmony_ci        /// Safely and falliably downcast to an immutable reference
16593da5c369Sopenharmony_ci        pub fn $fname(&self) -> Option<&$sockty> {
16603da5c369Sopenharmony_ci            if self.family() == Some($family)
16613da5c369Sopenharmony_ci                && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
16623da5c369Sopenharmony_ci            {
16633da5c369Sopenharmony_ci                // Safe because family and len are validated
16643da5c369Sopenharmony_ci                Some(unsafe { &self.$field })
16653da5c369Sopenharmony_ci            } else {
16663da5c369Sopenharmony_ci                None
16673da5c369Sopenharmony_ci            }
16683da5c369Sopenharmony_ci        }
16693da5c369Sopenharmony_ci
16703da5c369Sopenharmony_ci        /// Safely and falliably downcast to a mutable reference
16713da5c369Sopenharmony_ci        pub fn $fname_mut(&mut self) -> Option<&mut $sockty> {
16723da5c369Sopenharmony_ci            if self.family() == Some($family)
16733da5c369Sopenharmony_ci                && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
16743da5c369Sopenharmony_ci            {
16753da5c369Sopenharmony_ci                // Safe because family and len are validated
16763da5c369Sopenharmony_ci                Some(unsafe { &mut self.$field })
16773da5c369Sopenharmony_ci            } else {
16783da5c369Sopenharmony_ci                None
16793da5c369Sopenharmony_ci            }
16803da5c369Sopenharmony_ci        }
16813da5c369Sopenharmony_ci    };
16823da5c369Sopenharmony_ci}
16833da5c369Sopenharmony_ci
16843da5c369Sopenharmony_ciimpl SockaddrStorage {
16853da5c369Sopenharmony_ci    /// Downcast to an immutable `[UnixAddr]` reference.
16863da5c369Sopenharmony_ci    pub fn as_unix_addr(&self) -> Option<&UnixAddr> {
16873da5c369Sopenharmony_ci        cfg_if! {
16883da5c369Sopenharmony_ci            if #[cfg(any(target_os = "android",
16893da5c369Sopenharmony_ci                     target_os = "fuchsia",
16903da5c369Sopenharmony_ci                     target_os = "illumos",
16913da5c369Sopenharmony_ci                     target_os = "linux"
16923da5c369Sopenharmony_ci                ))]
16933da5c369Sopenharmony_ci            {
16943da5c369Sopenharmony_ci                let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
16953da5c369Sopenharmony_ci                // Safe because UnixAddr is strictly smaller than
16963da5c369Sopenharmony_ci                // sockaddr_storage, and we're fully initialized
16973da5c369Sopenharmony_ci                let len = unsafe {
16983da5c369Sopenharmony_ci                    (*(p as *const UnixAddr )).sun_len as usize
16993da5c369Sopenharmony_ci                };
17003da5c369Sopenharmony_ci            } else {
17013da5c369Sopenharmony_ci                let len = self.len() as usize;
17023da5c369Sopenharmony_ci            }
17033da5c369Sopenharmony_ci        }
17043da5c369Sopenharmony_ci        // Sanity checks
17053da5c369Sopenharmony_ci        if self.family() != Some(AddressFamily::Unix) ||
17063da5c369Sopenharmony_ci           len < offset_of!(libc::sockaddr_un, sun_path) ||
17073da5c369Sopenharmony_ci           len > mem::size_of::<libc::sockaddr_un>() {
17083da5c369Sopenharmony_ci            None
17093da5c369Sopenharmony_ci        } else {
17103da5c369Sopenharmony_ci            Some(unsafe{&self.su})
17113da5c369Sopenharmony_ci        }
17123da5c369Sopenharmony_ci    }
17133da5c369Sopenharmony_ci
17143da5c369Sopenharmony_ci    /// Downcast to a mutable `[UnixAddr]` reference.
17153da5c369Sopenharmony_ci    pub fn as_unix_addr_mut(&mut self) -> Option<&mut UnixAddr> {
17163da5c369Sopenharmony_ci        cfg_if! {
17173da5c369Sopenharmony_ci            if #[cfg(any(target_os = "android",
17183da5c369Sopenharmony_ci                     target_os = "fuchsia",
17193da5c369Sopenharmony_ci                     target_os = "illumos",
17203da5c369Sopenharmony_ci                     target_os = "linux"
17213da5c369Sopenharmony_ci                ))]
17223da5c369Sopenharmony_ci            {
17233da5c369Sopenharmony_ci                let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
17243da5c369Sopenharmony_ci                // Safe because UnixAddr is strictly smaller than
17253da5c369Sopenharmony_ci                // sockaddr_storage, and we're fully initialized
17263da5c369Sopenharmony_ci                let len = unsafe {
17273da5c369Sopenharmony_ci                    (*(p as *const UnixAddr )).sun_len as usize
17283da5c369Sopenharmony_ci                };
17293da5c369Sopenharmony_ci            } else {
17303da5c369Sopenharmony_ci                let len = self.len() as usize;
17313da5c369Sopenharmony_ci            }
17323da5c369Sopenharmony_ci        }
17333da5c369Sopenharmony_ci        // Sanity checks
17343da5c369Sopenharmony_ci        if self.family() != Some(AddressFamily::Unix) ||
17353da5c369Sopenharmony_ci           len < offset_of!(libc::sockaddr_un, sun_path) ||
17363da5c369Sopenharmony_ci           len > mem::size_of::<libc::sockaddr_un>() {
17373da5c369Sopenharmony_ci            None
17383da5c369Sopenharmony_ci        } else {
17393da5c369Sopenharmony_ci            Some(unsafe{&mut self.su})
17403da5c369Sopenharmony_ci        }
17413da5c369Sopenharmony_ci    }
17423da5c369Sopenharmony_ci
17433da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
17443da5c369Sopenharmony_ci    accessors! {as_alg_addr, as_alg_addr_mut, AlgAddr,
17453da5c369Sopenharmony_ci    AddressFamily::Alg, libc::sockaddr_alg, alg}
17463da5c369Sopenharmony_ci
17473da5c369Sopenharmony_ci    #[cfg(any(
17483da5c369Sopenharmony_ci        target_os = "android",
17493da5c369Sopenharmony_ci        target_os = "fuchsia",
17503da5c369Sopenharmony_ci        target_os = "linux"
17513da5c369Sopenharmony_ci    ))]
17523da5c369Sopenharmony_ci    #[cfg(feature = "net")]
17533da5c369Sopenharmony_ci    accessors! {
17543da5c369Sopenharmony_ci    as_link_addr, as_link_addr_mut, LinkAddr,
17553da5c369Sopenharmony_ci    AddressFamily::Packet, libc::sockaddr_ll, dl}
17563da5c369Sopenharmony_ci
17573da5c369Sopenharmony_ci    #[cfg(any(
17583da5c369Sopenharmony_ci        target_os = "dragonfly",
17593da5c369Sopenharmony_ci        target_os = "freebsd",
17603da5c369Sopenharmony_ci        target_os = "ios",
17613da5c369Sopenharmony_ci        target_os = "macos",
17623da5c369Sopenharmony_ci        target_os = "illumos",
17633da5c369Sopenharmony_ci        target_os = "netbsd",
17643da5c369Sopenharmony_ci        target_os = "openbsd"
17653da5c369Sopenharmony_ci    ))]
17663da5c369Sopenharmony_ci    #[cfg(feature = "net")]
17673da5c369Sopenharmony_ci    accessors! {
17683da5c369Sopenharmony_ci    as_link_addr, as_link_addr_mut, LinkAddr,
17693da5c369Sopenharmony_ci    AddressFamily::Link, libc::sockaddr_dl, dl}
17703da5c369Sopenharmony_ci
17713da5c369Sopenharmony_ci    #[cfg(feature = "net")]
17723da5c369Sopenharmony_ci    accessors! {
17733da5c369Sopenharmony_ci    as_sockaddr_in, as_sockaddr_in_mut, SockaddrIn,
17743da5c369Sopenharmony_ci    AddressFamily::Inet, libc::sockaddr_in, sin}
17753da5c369Sopenharmony_ci
17763da5c369Sopenharmony_ci    #[cfg(feature = "net")]
17773da5c369Sopenharmony_ci    accessors! {
17783da5c369Sopenharmony_ci    as_sockaddr_in6, as_sockaddr_in6_mut, SockaddrIn6,
17793da5c369Sopenharmony_ci    AddressFamily::Inet6, libc::sockaddr_in6, sin6}
17803da5c369Sopenharmony_ci
17813da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
17823da5c369Sopenharmony_ci    accessors! {as_netlink_addr, as_netlink_addr_mut, NetlinkAddr,
17833da5c369Sopenharmony_ci    AddressFamily::Netlink, libc::sockaddr_nl, nl}
17843da5c369Sopenharmony_ci
17853da5c369Sopenharmony_ci    #[cfg(all(feature = "ioctl", any(target_os = "ios", target_os = "macos")))]
17863da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
17873da5c369Sopenharmony_ci    accessors! {as_sys_control_addr, as_sys_control_addr_mut, SysControlAddr,
17883da5c369Sopenharmony_ci    AddressFamily::System, libc::sockaddr_ctl, sctl}
17893da5c369Sopenharmony_ci
17903da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
17913da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
17923da5c369Sopenharmony_ci    accessors! {as_vsock_addr, as_vsock_addr_mut, VsockAddr,
17933da5c369Sopenharmony_ci    AddressFamily::Vsock, libc::sockaddr_vm, vsock}
17943da5c369Sopenharmony_ci}
17953da5c369Sopenharmony_ci
17963da5c369Sopenharmony_ciimpl fmt::Debug for SockaddrStorage {
17973da5c369Sopenharmony_ci    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
17983da5c369Sopenharmony_ci        f.debug_struct("SockaddrStorage")
17993da5c369Sopenharmony_ci            // Safe because sockaddr_storage has the least specific
18003da5c369Sopenharmony_ci            // field types
18013da5c369Sopenharmony_ci            .field("ss", unsafe { &self.ss })
18023da5c369Sopenharmony_ci            .finish()
18033da5c369Sopenharmony_ci    }
18043da5c369Sopenharmony_ci}
18053da5c369Sopenharmony_ci
18063da5c369Sopenharmony_ciimpl fmt::Display for SockaddrStorage {
18073da5c369Sopenharmony_ci    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
18083da5c369Sopenharmony_ci        unsafe {
18093da5c369Sopenharmony_ci            match self.ss.ss_family as i32 {
18103da5c369Sopenharmony_ci                #[cfg(any(target_os = "android", target_os = "linux"))]
18113da5c369Sopenharmony_ci                libc::AF_ALG => self.alg.fmt(f),
18123da5c369Sopenharmony_ci                #[cfg(feature = "net")]
18133da5c369Sopenharmony_ci                libc::AF_INET => self.sin.fmt(f),
18143da5c369Sopenharmony_ci                #[cfg(feature = "net")]
18153da5c369Sopenharmony_ci                libc::AF_INET6 => self.sin6.fmt(f),
18163da5c369Sopenharmony_ci                #[cfg(any(
18173da5c369Sopenharmony_ci                    target_os = "dragonfly",
18183da5c369Sopenharmony_ci                    target_os = "freebsd",
18193da5c369Sopenharmony_ci                    target_os = "ios",
18203da5c369Sopenharmony_ci                    target_os = "macos",
18213da5c369Sopenharmony_ci                    target_os = "illumos",
18223da5c369Sopenharmony_ci                    target_os = "netbsd",
18233da5c369Sopenharmony_ci                    target_os = "openbsd"
18243da5c369Sopenharmony_ci                ))]
18253da5c369Sopenharmony_ci                #[cfg(feature = "net")]
18263da5c369Sopenharmony_ci                libc::AF_LINK => self.dl.fmt(f),
18273da5c369Sopenharmony_ci                #[cfg(any(target_os = "android", target_os = "linux"))]
18283da5c369Sopenharmony_ci                libc::AF_NETLINK => self.nl.fmt(f),
18293da5c369Sopenharmony_ci                #[cfg(any(
18303da5c369Sopenharmony_ci                    target_os = "android",
18313da5c369Sopenharmony_ci                    target_os = "linux",
18323da5c369Sopenharmony_ci                    target_os = "fuchsia"
18333da5c369Sopenharmony_ci                ))]
18343da5c369Sopenharmony_ci                #[cfg(feature = "net")]
18353da5c369Sopenharmony_ci                libc::AF_PACKET => self.dl.fmt(f),
18363da5c369Sopenharmony_ci                #[cfg(any(target_os = "ios", target_os = "macos"))]
18373da5c369Sopenharmony_ci                #[cfg(feature = "ioctl")]
18383da5c369Sopenharmony_ci                libc::AF_SYSTEM => self.sctl.fmt(f),
18393da5c369Sopenharmony_ci                libc::AF_UNIX => self.su.fmt(f),
18403da5c369Sopenharmony_ci                #[cfg(any(target_os = "android", target_os = "linux"))]
18413da5c369Sopenharmony_ci                libc::AF_VSOCK => self.vsock.fmt(f),
18423da5c369Sopenharmony_ci                _ => "<Address family unspecified>".fmt(f),
18433da5c369Sopenharmony_ci            }
18443da5c369Sopenharmony_ci        }
18453da5c369Sopenharmony_ci    }
18463da5c369Sopenharmony_ci}
18473da5c369Sopenharmony_ci
18483da5c369Sopenharmony_ci#[cfg(feature = "net")]
18493da5c369Sopenharmony_ciimpl From<net::SocketAddrV4> for SockaddrStorage {
18503da5c369Sopenharmony_ci    fn from(s: net::SocketAddrV4) -> Self {
18513da5c369Sopenharmony_ci        unsafe {
18523da5c369Sopenharmony_ci            let mut ss: Self = mem::zeroed();
18533da5c369Sopenharmony_ci            ss.sin = SockaddrIn::from(s);
18543da5c369Sopenharmony_ci            ss
18553da5c369Sopenharmony_ci        }
18563da5c369Sopenharmony_ci    }
18573da5c369Sopenharmony_ci}
18583da5c369Sopenharmony_ci
18593da5c369Sopenharmony_ci#[cfg(feature = "net")]
18603da5c369Sopenharmony_ciimpl From<net::SocketAddrV6> for SockaddrStorage {
18613da5c369Sopenharmony_ci    fn from(s: net::SocketAddrV6) -> Self {
18623da5c369Sopenharmony_ci        unsafe {
18633da5c369Sopenharmony_ci            let mut ss: Self = mem::zeroed();
18643da5c369Sopenharmony_ci            ss.sin6 = SockaddrIn6::from(s);
18653da5c369Sopenharmony_ci            ss
18663da5c369Sopenharmony_ci        }
18673da5c369Sopenharmony_ci    }
18683da5c369Sopenharmony_ci}
18693da5c369Sopenharmony_ci
18703da5c369Sopenharmony_ci#[cfg(feature = "net")]
18713da5c369Sopenharmony_ciimpl From<net::SocketAddr> for SockaddrStorage {
18723da5c369Sopenharmony_ci    fn from(s: net::SocketAddr) -> Self {
18733da5c369Sopenharmony_ci        match s {
18743da5c369Sopenharmony_ci            net::SocketAddr::V4(sa4) => Self::from(sa4),
18753da5c369Sopenharmony_ci            net::SocketAddr::V6(sa6) => Self::from(sa6),
18763da5c369Sopenharmony_ci        }
18773da5c369Sopenharmony_ci    }
18783da5c369Sopenharmony_ci}
18793da5c369Sopenharmony_ci
18803da5c369Sopenharmony_ciimpl Hash for SockaddrStorage {
18813da5c369Sopenharmony_ci    fn hash<H: Hasher>(&self, s: &mut H) {
18823da5c369Sopenharmony_ci        unsafe {
18833da5c369Sopenharmony_ci            match self.ss.ss_family as i32 {
18843da5c369Sopenharmony_ci                #[cfg(any(target_os = "android", target_os = "linux"))]
18853da5c369Sopenharmony_ci                libc::AF_ALG => self.alg.hash(s),
18863da5c369Sopenharmony_ci                #[cfg(feature = "net")]
18873da5c369Sopenharmony_ci                libc::AF_INET => self.sin.hash(s),
18883da5c369Sopenharmony_ci                #[cfg(feature = "net")]
18893da5c369Sopenharmony_ci                libc::AF_INET6 => self.sin6.hash(s),
18903da5c369Sopenharmony_ci                #[cfg(any(
18913da5c369Sopenharmony_ci                    target_os = "dragonfly",
18923da5c369Sopenharmony_ci                    target_os = "freebsd",
18933da5c369Sopenharmony_ci                    target_os = "ios",
18943da5c369Sopenharmony_ci                    target_os = "macos",
18953da5c369Sopenharmony_ci                    target_os = "illumos",
18963da5c369Sopenharmony_ci                    target_os = "netbsd",
18973da5c369Sopenharmony_ci                    target_os = "openbsd"
18983da5c369Sopenharmony_ci                ))]
18993da5c369Sopenharmony_ci                #[cfg(feature = "net")]
19003da5c369Sopenharmony_ci                libc::AF_LINK => self.dl.hash(s),
19013da5c369Sopenharmony_ci                #[cfg(any(target_os = "android", target_os = "linux"))]
19023da5c369Sopenharmony_ci                libc::AF_NETLINK => self.nl.hash(s),
19033da5c369Sopenharmony_ci                #[cfg(any(
19043da5c369Sopenharmony_ci                    target_os = "android",
19053da5c369Sopenharmony_ci                    target_os = "linux",
19063da5c369Sopenharmony_ci                    target_os = "fuchsia"
19073da5c369Sopenharmony_ci                ))]
19083da5c369Sopenharmony_ci                #[cfg(feature = "net")]
19093da5c369Sopenharmony_ci                libc::AF_PACKET => self.dl.hash(s),
19103da5c369Sopenharmony_ci                #[cfg(any(target_os = "ios", target_os = "macos"))]
19113da5c369Sopenharmony_ci                #[cfg(feature = "ioctl")]
19123da5c369Sopenharmony_ci                libc::AF_SYSTEM => self.sctl.hash(s),
19133da5c369Sopenharmony_ci                libc::AF_UNIX => self.su.hash(s),
19143da5c369Sopenharmony_ci                #[cfg(any(target_os = "android", target_os = "linux"))]
19153da5c369Sopenharmony_ci                libc::AF_VSOCK => self.vsock.hash(s),
19163da5c369Sopenharmony_ci                _ => self.ss.hash(s),
19173da5c369Sopenharmony_ci            }
19183da5c369Sopenharmony_ci        }
19193da5c369Sopenharmony_ci    }
19203da5c369Sopenharmony_ci}
19213da5c369Sopenharmony_ci
19223da5c369Sopenharmony_ciimpl PartialEq for SockaddrStorage {
19233da5c369Sopenharmony_ci    fn eq(&self, other: &Self) -> bool {
19243da5c369Sopenharmony_ci        unsafe {
19253da5c369Sopenharmony_ci            match (self.ss.ss_family as i32, other.ss.ss_family as i32) {
19263da5c369Sopenharmony_ci                #[cfg(any(target_os = "android", target_os = "linux"))]
19273da5c369Sopenharmony_ci                (libc::AF_ALG, libc::AF_ALG) => self.alg == other.alg,
19283da5c369Sopenharmony_ci                #[cfg(feature = "net")]
19293da5c369Sopenharmony_ci                (libc::AF_INET, libc::AF_INET) => self.sin == other.sin,
19303da5c369Sopenharmony_ci                #[cfg(feature = "net")]
19313da5c369Sopenharmony_ci                (libc::AF_INET6, libc::AF_INET6) => self.sin6 == other.sin6,
19323da5c369Sopenharmony_ci                #[cfg(any(
19333da5c369Sopenharmony_ci                    target_os = "dragonfly",
19343da5c369Sopenharmony_ci                    target_os = "freebsd",
19353da5c369Sopenharmony_ci                    target_os = "ios",
19363da5c369Sopenharmony_ci                    target_os = "macos",
19373da5c369Sopenharmony_ci                    target_os = "illumos",
19383da5c369Sopenharmony_ci                    target_os = "netbsd",
19393da5c369Sopenharmony_ci                    target_os = "openbsd"
19403da5c369Sopenharmony_ci                ))]
19413da5c369Sopenharmony_ci                #[cfg(feature = "net")]
19423da5c369Sopenharmony_ci                (libc::AF_LINK, libc::AF_LINK) => self.dl == other.dl,
19433da5c369Sopenharmony_ci                #[cfg(any(target_os = "android", target_os = "linux"))]
19443da5c369Sopenharmony_ci                (libc::AF_NETLINK, libc::AF_NETLINK) => self.nl == other.nl,
19453da5c369Sopenharmony_ci                #[cfg(any(
19463da5c369Sopenharmony_ci                    target_os = "android",
19473da5c369Sopenharmony_ci                    target_os = "fuchsia",
19483da5c369Sopenharmony_ci                    target_os = "linux"
19493da5c369Sopenharmony_ci                ))]
19503da5c369Sopenharmony_ci                #[cfg(feature = "net")]
19513da5c369Sopenharmony_ci                (libc::AF_PACKET, libc::AF_PACKET) => self.dl == other.dl,
19523da5c369Sopenharmony_ci                #[cfg(any(target_os = "ios", target_os = "macos"))]
19533da5c369Sopenharmony_ci                #[cfg(feature = "ioctl")]
19543da5c369Sopenharmony_ci                (libc::AF_SYSTEM, libc::AF_SYSTEM) => self.sctl == other.sctl,
19553da5c369Sopenharmony_ci                (libc::AF_UNIX, libc::AF_UNIX) => self.su == other.su,
19563da5c369Sopenharmony_ci                #[cfg(any(target_os = "android", target_os = "linux"))]
19573da5c369Sopenharmony_ci                (libc::AF_VSOCK, libc::AF_VSOCK) => self.vsock == other.vsock,
19583da5c369Sopenharmony_ci                _ => false,
19593da5c369Sopenharmony_ci            }
19603da5c369Sopenharmony_ci        }
19613da5c369Sopenharmony_ci    }
19623da5c369Sopenharmony_ci}
19633da5c369Sopenharmony_ci
19643da5c369Sopenharmony_cimod private {
19653da5c369Sopenharmony_ci    pub trait SockaddrLikePriv {
19663da5c369Sopenharmony_ci        /// Returns a mutable raw pointer to the inner structure.
19673da5c369Sopenharmony_ci        ///
19683da5c369Sopenharmony_ci        /// # Safety
19693da5c369Sopenharmony_ci        ///
19703da5c369Sopenharmony_ci        /// This method is technically safe, but modifying the inner structure's
19713da5c369Sopenharmony_ci        /// `family` or `len` fields may result in violating Nix's invariants.
19723da5c369Sopenharmony_ci        /// It is best to use this method only with foreign functions that do
19733da5c369Sopenharmony_ci        /// not change the sockaddr type.
19743da5c369Sopenharmony_ci        fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
19753da5c369Sopenharmony_ci            self as *mut Self as *mut libc::sockaddr
19763da5c369Sopenharmony_ci        }
19773da5c369Sopenharmony_ci    }
19783da5c369Sopenharmony_ci}
19793da5c369Sopenharmony_ci
19803da5c369Sopenharmony_ci/// Represents a socket address
19813da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
19823da5c369Sopenharmony_ci#[deprecated(
19833da5c369Sopenharmony_ci    since = "0.24.0",
19843da5c369Sopenharmony_ci    note = "use SockaddrLike or SockaddrStorage instead"
19853da5c369Sopenharmony_ci)]
19863da5c369Sopenharmony_ci#[allow(missing_docs)] // Since they're all deprecated anyway
19873da5c369Sopenharmony_ci#[allow(deprecated)]
19883da5c369Sopenharmony_ci#[non_exhaustive]
19893da5c369Sopenharmony_cipub enum SockAddr {
19903da5c369Sopenharmony_ci    #[cfg(feature = "net")]
19913da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
19923da5c369Sopenharmony_ci    Inet(InetAddr),
19933da5c369Sopenharmony_ci    Unix(UnixAddr),
19943da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
19953da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
19963da5c369Sopenharmony_ci    Netlink(NetlinkAddr),
19973da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
19983da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
19993da5c369Sopenharmony_ci    Alg(AlgAddr),
20003da5c369Sopenharmony_ci    #[cfg(all(
20013da5c369Sopenharmony_ci        feature = "ioctl",
20023da5c369Sopenharmony_ci        any(target_os = "ios", target_os = "macos")
20033da5c369Sopenharmony_ci    ))]
20043da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
20053da5c369Sopenharmony_ci    SysControl(SysControlAddr),
20063da5c369Sopenharmony_ci    /// Datalink address (MAC)
20073da5c369Sopenharmony_ci    #[cfg(any(
20083da5c369Sopenharmony_ci        target_os = "android",
20093da5c369Sopenharmony_ci        target_os = "dragonfly",
20103da5c369Sopenharmony_ci        target_os = "freebsd",
20113da5c369Sopenharmony_ci        target_os = "ios",
20123da5c369Sopenharmony_ci        target_os = "linux",
20133da5c369Sopenharmony_ci        target_os = "macos",
20143da5c369Sopenharmony_ci        target_os = "illumos",
20153da5c369Sopenharmony_ci        target_os = "netbsd",
20163da5c369Sopenharmony_ci        target_os = "openbsd"
20173da5c369Sopenharmony_ci    ))]
20183da5c369Sopenharmony_ci    #[cfg(feature = "net")]
20193da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
20203da5c369Sopenharmony_ci    Link(LinkAddr),
20213da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
20223da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
20233da5c369Sopenharmony_ci    Vsock(VsockAddr),
20243da5c369Sopenharmony_ci}
20253da5c369Sopenharmony_ci
20263da5c369Sopenharmony_ci#[allow(missing_docs)] // Since they're all deprecated anyway
20273da5c369Sopenharmony_ci#[allow(deprecated)]
20283da5c369Sopenharmony_ciimpl SockAddr {
20293da5c369Sopenharmony_ci    feature! {
20303da5c369Sopenharmony_ci    #![feature = "net"]
20313da5c369Sopenharmony_ci    pub fn new_inet(addr: InetAddr) -> SockAddr {
20323da5c369Sopenharmony_ci        SockAddr::Inet(addr)
20333da5c369Sopenharmony_ci    }
20343da5c369Sopenharmony_ci    }
20353da5c369Sopenharmony_ci
20363da5c369Sopenharmony_ci    pub fn new_unix<P: ?Sized + NixPath>(path: &P) -> Result<SockAddr> {
20373da5c369Sopenharmony_ci        Ok(SockAddr::Unix(UnixAddr::new(path)?))
20383da5c369Sopenharmony_ci    }
20393da5c369Sopenharmony_ci
20403da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
20413da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
20423da5c369Sopenharmony_ci    pub fn new_netlink(pid: u32, groups: u32) -> SockAddr {
20433da5c369Sopenharmony_ci        SockAddr::Netlink(NetlinkAddr::new(pid, groups))
20443da5c369Sopenharmony_ci    }
20453da5c369Sopenharmony_ci
20463da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
20473da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
20483da5c369Sopenharmony_ci    pub fn new_alg(alg_type: &str, alg_name: &str) -> SockAddr {
20493da5c369Sopenharmony_ci        SockAddr::Alg(AlgAddr::new(alg_type, alg_name))
20503da5c369Sopenharmony_ci    }
20513da5c369Sopenharmony_ci
20523da5c369Sopenharmony_ci    feature! {
20533da5c369Sopenharmony_ci    #![feature = "ioctl"]
20543da5c369Sopenharmony_ci    #[cfg(any(target_os = "ios", target_os = "macos"))]
20553da5c369Sopenharmony_ci    pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> {
20563da5c369Sopenharmony_ci        SysControlAddr::from_name(sockfd, name, unit).map(SockAddr::SysControl)
20573da5c369Sopenharmony_ci    }
20583da5c369Sopenharmony_ci    }
20593da5c369Sopenharmony_ci
20603da5c369Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
20613da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
20623da5c369Sopenharmony_ci    pub fn new_vsock(cid: u32, port: u32) -> SockAddr {
20633da5c369Sopenharmony_ci        SockAddr::Vsock(VsockAddr::new(cid, port))
20643da5c369Sopenharmony_ci    }
20653da5c369Sopenharmony_ci
20663da5c369Sopenharmony_ci    pub fn family(&self) -> AddressFamily {
20673da5c369Sopenharmony_ci        match *self {
20683da5c369Sopenharmony_ci            #[cfg(feature = "net")]
20693da5c369Sopenharmony_ci            SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
20703da5c369Sopenharmony_ci            #[cfg(feature = "net")]
20713da5c369Sopenharmony_ci            SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6,
20723da5c369Sopenharmony_ci            SockAddr::Unix(..) => AddressFamily::Unix,
20733da5c369Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
20743da5c369Sopenharmony_ci            SockAddr::Netlink(..) => AddressFamily::Netlink,
20753da5c369Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
20763da5c369Sopenharmony_ci            SockAddr::Alg(..) => AddressFamily::Alg,
20773da5c369Sopenharmony_ci            #[cfg(all(
20783da5c369Sopenharmony_ci                feature = "ioctl",
20793da5c369Sopenharmony_ci                any(target_os = "ios", target_os = "macos")
20803da5c369Sopenharmony_ci            ))]
20813da5c369Sopenharmony_ci            SockAddr::SysControl(..) => AddressFamily::System,
20823da5c369Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
20833da5c369Sopenharmony_ci            #[cfg(feature = "net")]
20843da5c369Sopenharmony_ci            SockAddr::Link(..) => AddressFamily::Packet,
20853da5c369Sopenharmony_ci            #[cfg(any(
20863da5c369Sopenharmony_ci                target_os = "dragonfly",
20873da5c369Sopenharmony_ci                target_os = "freebsd",
20883da5c369Sopenharmony_ci                target_os = "ios",
20893da5c369Sopenharmony_ci                target_os = "macos",
20903da5c369Sopenharmony_ci                target_os = "netbsd",
20913da5c369Sopenharmony_ci                target_os = "illumos",
20923da5c369Sopenharmony_ci                target_os = "openbsd"
20933da5c369Sopenharmony_ci            ))]
20943da5c369Sopenharmony_ci            #[cfg(feature = "net")]
20953da5c369Sopenharmony_ci            SockAddr::Link(..) => AddressFamily::Link,
20963da5c369Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
20973da5c369Sopenharmony_ci            SockAddr::Vsock(..) => AddressFamily::Vsock,
20983da5c369Sopenharmony_ci        }
20993da5c369Sopenharmony_ci    }
21003da5c369Sopenharmony_ci
21013da5c369Sopenharmony_ci    #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
21023da5c369Sopenharmony_ci    pub fn to_str(&self) -> String {
21033da5c369Sopenharmony_ci        format!("{}", self)
21043da5c369Sopenharmony_ci    }
21053da5c369Sopenharmony_ci
21063da5c369Sopenharmony_ci    /// Creates a `SockAddr` struct from libc's sockaddr.
21073da5c369Sopenharmony_ci    ///
21083da5c369Sopenharmony_ci    /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System.
21093da5c369Sopenharmony_ci    /// Returns None for unsupported families.
21103da5c369Sopenharmony_ci    ///
21113da5c369Sopenharmony_ci    /// # Safety
21123da5c369Sopenharmony_ci    ///
21133da5c369Sopenharmony_ci    /// unsafe because it takes a raw pointer as argument.  The caller must
21143da5c369Sopenharmony_ci    /// ensure that the pointer is valid.
21153da5c369Sopenharmony_ci    #[cfg(not(target_os = "fuchsia"))]
21163da5c369Sopenharmony_ci    #[cfg(feature = "net")]
21173da5c369Sopenharmony_ci    pub(crate) unsafe fn from_libc_sockaddr(
21183da5c369Sopenharmony_ci        addr: *const libc::sockaddr,
21193da5c369Sopenharmony_ci    ) -> Option<SockAddr> {
21203da5c369Sopenharmony_ci        if addr.is_null() {
21213da5c369Sopenharmony_ci            None
21223da5c369Sopenharmony_ci        } else {
21233da5c369Sopenharmony_ci            match AddressFamily::from_i32(i32::from((*addr).sa_family)) {
21243da5c369Sopenharmony_ci                Some(AddressFamily::Unix) => None,
21253da5c369Sopenharmony_ci                #[cfg(feature = "net")]
21263da5c369Sopenharmony_ci                Some(AddressFamily::Inet) => Some(SockAddr::Inet(
21273da5c369Sopenharmony_ci                    InetAddr::V4(ptr::read_unaligned(addr as *const _)),
21283da5c369Sopenharmony_ci                )),
21293da5c369Sopenharmony_ci                #[cfg(feature = "net")]
21303da5c369Sopenharmony_ci                Some(AddressFamily::Inet6) => Some(SockAddr::Inet(
21313da5c369Sopenharmony_ci                    InetAddr::V6(ptr::read_unaligned(addr as *const _)),
21323da5c369Sopenharmony_ci                )),
21333da5c369Sopenharmony_ci                #[cfg(any(target_os = "android", target_os = "linux"))]
21343da5c369Sopenharmony_ci                Some(AddressFamily::Netlink) => Some(SockAddr::Netlink(
21353da5c369Sopenharmony_ci                    NetlinkAddr(ptr::read_unaligned(addr as *const _)),
21363da5c369Sopenharmony_ci                )),
21373da5c369Sopenharmony_ci                #[cfg(all(
21383da5c369Sopenharmony_ci                    feature = "ioctl",
21393da5c369Sopenharmony_ci                    any(target_os = "ios", target_os = "macos")
21403da5c369Sopenharmony_ci                ))]
21413da5c369Sopenharmony_ci                Some(AddressFamily::System) => Some(SockAddr::SysControl(
21423da5c369Sopenharmony_ci                    SysControlAddr(ptr::read_unaligned(addr as *const _)),
21433da5c369Sopenharmony_ci                )),
21443da5c369Sopenharmony_ci                #[cfg(any(target_os = "android", target_os = "linux"))]
21453da5c369Sopenharmony_ci                #[cfg(feature = "net")]
21463da5c369Sopenharmony_ci                Some(AddressFamily::Packet) => Some(SockAddr::Link(LinkAddr(
21473da5c369Sopenharmony_ci                    ptr::read_unaligned(addr as *const _),
21483da5c369Sopenharmony_ci                ))),
21493da5c369Sopenharmony_ci                #[cfg(any(
21503da5c369Sopenharmony_ci                    target_os = "dragonfly",
21513da5c369Sopenharmony_ci                    target_os = "freebsd",
21523da5c369Sopenharmony_ci                    target_os = "ios",
21533da5c369Sopenharmony_ci                    target_os = "macos",
21543da5c369Sopenharmony_ci                    target_os = "netbsd",
21553da5c369Sopenharmony_ci                    target_os = "illumos",
21563da5c369Sopenharmony_ci                    target_os = "openbsd"
21573da5c369Sopenharmony_ci                ))]
21583da5c369Sopenharmony_ci                #[cfg(feature = "net")]
21593da5c369Sopenharmony_ci                Some(AddressFamily::Link) => {
21603da5c369Sopenharmony_ci                    let ether_addr =
21613da5c369Sopenharmony_ci                        LinkAddr(ptr::read_unaligned(addr as *const _));
21623da5c369Sopenharmony_ci                    if ether_addr.is_empty() {
21633da5c369Sopenharmony_ci                        None
21643da5c369Sopenharmony_ci                    } else {
21653da5c369Sopenharmony_ci                        Some(SockAddr::Link(ether_addr))
21663da5c369Sopenharmony_ci                    }
21673da5c369Sopenharmony_ci                }
21683da5c369Sopenharmony_ci                #[cfg(any(target_os = "android", target_os = "linux"))]
21693da5c369Sopenharmony_ci                Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(VsockAddr(
21703da5c369Sopenharmony_ci                    ptr::read_unaligned(addr as *const _),
21713da5c369Sopenharmony_ci                ))),
21723da5c369Sopenharmony_ci                // Other address families are currently not supported and simply yield a None
21733da5c369Sopenharmony_ci                // entry instead of a proper conversion to a `SockAddr`.
21743da5c369Sopenharmony_ci                Some(_) | None => None,
21753da5c369Sopenharmony_ci            }
21763da5c369Sopenharmony_ci        }
21773da5c369Sopenharmony_ci    }
21783da5c369Sopenharmony_ci
21793da5c369Sopenharmony_ci    /// Conversion from nix's SockAddr type to the underlying libc sockaddr type.
21803da5c369Sopenharmony_ci    ///
21813da5c369Sopenharmony_ci    /// This is useful for interfacing with other libc functions that don't yet have nix wrappers.
21823da5c369Sopenharmony_ci    /// Returns a reference to the underlying data type (as a sockaddr reference) along
21833da5c369Sopenharmony_ci    /// with the size of the actual data type. sockaddr is commonly used as a proxy for
21843da5c369Sopenharmony_ci    /// a superclass as C doesn't support inheritance, so many functions that take
21853da5c369Sopenharmony_ci    /// a sockaddr * need to take the size of the underlying type as well and then internally cast it back.
21863da5c369Sopenharmony_ci    pub fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
21873da5c369Sopenharmony_ci        match *self {
21883da5c369Sopenharmony_ci            #[cfg(feature = "net")]
21893da5c369Sopenharmony_ci            SockAddr::Inet(InetAddr::V4(ref addr)) => (
21903da5c369Sopenharmony_ci                // This cast is always allowed in C
21913da5c369Sopenharmony_ci                unsafe {
21923da5c369Sopenharmony_ci                    &*(addr as *const libc::sockaddr_in
21933da5c369Sopenharmony_ci                        as *const libc::sockaddr)
21943da5c369Sopenharmony_ci                },
21953da5c369Sopenharmony_ci                mem::size_of_val(addr) as libc::socklen_t,
21963da5c369Sopenharmony_ci            ),
21973da5c369Sopenharmony_ci            #[cfg(feature = "net")]
21983da5c369Sopenharmony_ci            SockAddr::Inet(InetAddr::V6(ref addr)) => (
21993da5c369Sopenharmony_ci                // This cast is always allowed in C
22003da5c369Sopenharmony_ci                unsafe {
22013da5c369Sopenharmony_ci                    &*(addr as *const libc::sockaddr_in6
22023da5c369Sopenharmony_ci                        as *const libc::sockaddr)
22033da5c369Sopenharmony_ci                },
22043da5c369Sopenharmony_ci                mem::size_of_val(addr) as libc::socklen_t,
22053da5c369Sopenharmony_ci            ),
22063da5c369Sopenharmony_ci            SockAddr::Unix(ref unix_addr) => (
22073da5c369Sopenharmony_ci                // This cast is always allowed in C
22083da5c369Sopenharmony_ci                unsafe {
22093da5c369Sopenharmony_ci                    &*(&unix_addr.sun as *const libc::sockaddr_un
22103da5c369Sopenharmony_ci                        as *const libc::sockaddr)
22113da5c369Sopenharmony_ci                },
22123da5c369Sopenharmony_ci                unix_addr.sun_len() as libc::socklen_t,
22133da5c369Sopenharmony_ci            ),
22143da5c369Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
22153da5c369Sopenharmony_ci            SockAddr::Netlink(NetlinkAddr(ref sa)) => (
22163da5c369Sopenharmony_ci                // This cast is always allowed in C
22173da5c369Sopenharmony_ci                unsafe {
22183da5c369Sopenharmony_ci                    &*(sa as *const libc::sockaddr_nl as *const libc::sockaddr)
22193da5c369Sopenharmony_ci                },
22203da5c369Sopenharmony_ci                mem::size_of_val(sa) as libc::socklen_t,
22213da5c369Sopenharmony_ci            ),
22223da5c369Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
22233da5c369Sopenharmony_ci            SockAddr::Alg(AlgAddr(ref sa)) => (
22243da5c369Sopenharmony_ci                // This cast is always allowed in C
22253da5c369Sopenharmony_ci                unsafe {
22263da5c369Sopenharmony_ci                    &*(sa as *const libc::sockaddr_alg as *const libc::sockaddr)
22273da5c369Sopenharmony_ci                },
22283da5c369Sopenharmony_ci                mem::size_of_val(sa) as libc::socklen_t,
22293da5c369Sopenharmony_ci            ),
22303da5c369Sopenharmony_ci            #[cfg(all(
22313da5c369Sopenharmony_ci                feature = "ioctl",
22323da5c369Sopenharmony_ci                any(target_os = "ios", target_os = "macos")
22333da5c369Sopenharmony_ci            ))]
22343da5c369Sopenharmony_ci            SockAddr::SysControl(SysControlAddr(ref sa)) => (
22353da5c369Sopenharmony_ci                // This cast is always allowed in C
22363da5c369Sopenharmony_ci                unsafe {
22373da5c369Sopenharmony_ci                    &*(sa as *const libc::sockaddr_ctl as *const libc::sockaddr)
22383da5c369Sopenharmony_ci                },
22393da5c369Sopenharmony_ci                mem::size_of_val(sa) as libc::socklen_t,
22403da5c369Sopenharmony_ci            ),
22413da5c369Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
22423da5c369Sopenharmony_ci            #[cfg(feature = "net")]
22433da5c369Sopenharmony_ci            SockAddr::Link(LinkAddr(ref addr)) => (
22443da5c369Sopenharmony_ci                // This cast is always allowed in C
22453da5c369Sopenharmony_ci                unsafe {
22463da5c369Sopenharmony_ci                    &*(addr as *const libc::sockaddr_ll
22473da5c369Sopenharmony_ci                        as *const libc::sockaddr)
22483da5c369Sopenharmony_ci                },
22493da5c369Sopenharmony_ci                mem::size_of_val(addr) as libc::socklen_t,
22503da5c369Sopenharmony_ci            ),
22513da5c369Sopenharmony_ci            #[cfg(any(
22523da5c369Sopenharmony_ci                target_os = "dragonfly",
22533da5c369Sopenharmony_ci                target_os = "freebsd",
22543da5c369Sopenharmony_ci                target_os = "ios",
22553da5c369Sopenharmony_ci                target_os = "macos",
22563da5c369Sopenharmony_ci                target_os = "illumos",
22573da5c369Sopenharmony_ci                target_os = "netbsd",
22583da5c369Sopenharmony_ci                target_os = "openbsd"
22593da5c369Sopenharmony_ci            ))]
22603da5c369Sopenharmony_ci            #[cfg(feature = "net")]
22613da5c369Sopenharmony_ci            SockAddr::Link(LinkAddr(ref addr)) => (
22623da5c369Sopenharmony_ci                // This cast is always allowed in C
22633da5c369Sopenharmony_ci                unsafe {
22643da5c369Sopenharmony_ci                    &*(addr as *const libc::sockaddr_dl
22653da5c369Sopenharmony_ci                        as *const libc::sockaddr)
22663da5c369Sopenharmony_ci                },
22673da5c369Sopenharmony_ci                mem::size_of_val(addr) as libc::socklen_t,
22683da5c369Sopenharmony_ci            ),
22693da5c369Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
22703da5c369Sopenharmony_ci            SockAddr::Vsock(VsockAddr(ref sa)) => (
22713da5c369Sopenharmony_ci                // This cast is always allowed in C
22723da5c369Sopenharmony_ci                unsafe {
22733da5c369Sopenharmony_ci                    &*(sa as *const libc::sockaddr_vm as *const libc::sockaddr)
22743da5c369Sopenharmony_ci                },
22753da5c369Sopenharmony_ci                mem::size_of_val(sa) as libc::socklen_t,
22763da5c369Sopenharmony_ci            ),
22773da5c369Sopenharmony_ci        }
22783da5c369Sopenharmony_ci    }
22793da5c369Sopenharmony_ci}
22803da5c369Sopenharmony_ci
22813da5c369Sopenharmony_ci#[allow(deprecated)]
22823da5c369Sopenharmony_ciimpl fmt::Display for SockAddr {
22833da5c369Sopenharmony_ci    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22843da5c369Sopenharmony_ci        match *self {
22853da5c369Sopenharmony_ci            #[cfg(feature = "net")]
22863da5c369Sopenharmony_ci            SockAddr::Inet(ref inet) => inet.fmt(f),
22873da5c369Sopenharmony_ci            SockAddr::Unix(ref unix) => unix.fmt(f),
22883da5c369Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
22893da5c369Sopenharmony_ci            SockAddr::Netlink(ref nl) => nl.fmt(f),
22903da5c369Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
22913da5c369Sopenharmony_ci            SockAddr::Alg(ref nl) => nl.fmt(f),
22923da5c369Sopenharmony_ci            #[cfg(all(
22933da5c369Sopenharmony_ci                feature = "ioctl",
22943da5c369Sopenharmony_ci                any(target_os = "ios", target_os = "macos")
22953da5c369Sopenharmony_ci            ))]
22963da5c369Sopenharmony_ci            SockAddr::SysControl(ref sc) => sc.fmt(f),
22973da5c369Sopenharmony_ci            #[cfg(any(
22983da5c369Sopenharmony_ci                target_os = "android",
22993da5c369Sopenharmony_ci                target_os = "dragonfly",
23003da5c369Sopenharmony_ci                target_os = "freebsd",
23013da5c369Sopenharmony_ci                target_os = "ios",
23023da5c369Sopenharmony_ci                target_os = "linux",
23033da5c369Sopenharmony_ci                target_os = "macos",
23043da5c369Sopenharmony_ci                target_os = "netbsd",
23053da5c369Sopenharmony_ci                target_os = "illumos",
23063da5c369Sopenharmony_ci                target_os = "openbsd"
23073da5c369Sopenharmony_ci            ))]
23083da5c369Sopenharmony_ci            #[cfg(feature = "net")]
23093da5c369Sopenharmony_ci            SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
23103da5c369Sopenharmony_ci            #[cfg(any(target_os = "android", target_os = "linux"))]
23113da5c369Sopenharmony_ci            SockAddr::Vsock(ref svm) => svm.fmt(f),
23123da5c369Sopenharmony_ci        }
23133da5c369Sopenharmony_ci    }
23143da5c369Sopenharmony_ci}
23153da5c369Sopenharmony_ci
23163da5c369Sopenharmony_ci#[cfg(not(target_os = "fuchsia"))]
23173da5c369Sopenharmony_ci#[cfg(feature = "net")]
23183da5c369Sopenharmony_ci#[allow(deprecated)]
23193da5c369Sopenharmony_ciimpl private::SockaddrLikePriv for SockAddr {}
23203da5c369Sopenharmony_ci#[cfg(not(target_os = "fuchsia"))]
23213da5c369Sopenharmony_ci#[cfg(feature = "net")]
23223da5c369Sopenharmony_ci#[allow(deprecated)]
23233da5c369Sopenharmony_ciimpl SockaddrLike for SockAddr {
23243da5c369Sopenharmony_ci    unsafe fn from_raw(
23253da5c369Sopenharmony_ci        addr: *const libc::sockaddr,
23263da5c369Sopenharmony_ci        _len: Option<libc::socklen_t>,
23273da5c369Sopenharmony_ci    ) -> Option<Self> {
23283da5c369Sopenharmony_ci        Self::from_libc_sockaddr(addr)
23293da5c369Sopenharmony_ci    }
23303da5c369Sopenharmony_ci}
23313da5c369Sopenharmony_ci
23323da5c369Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
23333da5c369Sopenharmony_ci#[cfg_attr(docsrs, doc(cfg(all())))]
23343da5c369Sopenharmony_cipub mod netlink {
23353da5c369Sopenharmony_ci    use super::*;
23363da5c369Sopenharmony_ci    use crate::sys::socket::addr::AddressFamily;
23373da5c369Sopenharmony_ci    use libc::{sa_family_t, sockaddr_nl};
23383da5c369Sopenharmony_ci    use std::{fmt, mem};
23393da5c369Sopenharmony_ci
23403da5c369Sopenharmony_ci    /// Address for the Linux kernel user interface device.
23413da5c369Sopenharmony_ci    ///
23423da5c369Sopenharmony_ci    /// # References
23433da5c369Sopenharmony_ci    ///
23443da5c369Sopenharmony_ci    /// [netlink(7)](https://man7.org/linux/man-pages/man7/netlink.7.html)
23453da5c369Sopenharmony_ci    #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
23463da5c369Sopenharmony_ci    #[repr(transparent)]
23473da5c369Sopenharmony_ci    pub struct NetlinkAddr(pub(in super::super) sockaddr_nl);
23483da5c369Sopenharmony_ci
23493da5c369Sopenharmony_ci    impl NetlinkAddr {
23503da5c369Sopenharmony_ci        /// Construct a new socket address from its port ID and multicast groups
23513da5c369Sopenharmony_ci        /// mask.
23523da5c369Sopenharmony_ci        pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
23533da5c369Sopenharmony_ci            let mut addr: sockaddr_nl = unsafe { mem::zeroed() };
23543da5c369Sopenharmony_ci            addr.nl_family = AddressFamily::Netlink as sa_family_t;
23553da5c369Sopenharmony_ci            addr.nl_pid = pid;
23563da5c369Sopenharmony_ci            addr.nl_groups = groups;
23573da5c369Sopenharmony_ci
23583da5c369Sopenharmony_ci            NetlinkAddr(addr)
23593da5c369Sopenharmony_ci        }
23603da5c369Sopenharmony_ci
23613da5c369Sopenharmony_ci        /// Return the socket's port ID.
23623da5c369Sopenharmony_ci        pub const fn pid(&self) -> u32 {
23633da5c369Sopenharmony_ci            self.0.nl_pid
23643da5c369Sopenharmony_ci        }
23653da5c369Sopenharmony_ci
23663da5c369Sopenharmony_ci        /// Return the socket's multicast groups mask
23673da5c369Sopenharmony_ci        pub const fn groups(&self) -> u32 {
23683da5c369Sopenharmony_ci            self.0.nl_groups
23693da5c369Sopenharmony_ci        }
23703da5c369Sopenharmony_ci    }
23713da5c369Sopenharmony_ci
23723da5c369Sopenharmony_ci    impl private::SockaddrLikePriv for NetlinkAddr {}
23733da5c369Sopenharmony_ci    impl SockaddrLike for NetlinkAddr {
23743da5c369Sopenharmony_ci        unsafe fn from_raw(
23753da5c369Sopenharmony_ci            addr: *const libc::sockaddr,
23763da5c369Sopenharmony_ci            len: Option<libc::socklen_t>,
23773da5c369Sopenharmony_ci        ) -> Option<Self>
23783da5c369Sopenharmony_ci        where
23793da5c369Sopenharmony_ci            Self: Sized,
23803da5c369Sopenharmony_ci        {
23813da5c369Sopenharmony_ci            if let Some(l) = len {
23823da5c369Sopenharmony_ci                if l != mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t {
23833da5c369Sopenharmony_ci                    return None;
23843da5c369Sopenharmony_ci                }
23853da5c369Sopenharmony_ci            }
23863da5c369Sopenharmony_ci            if (*addr).sa_family as i32 != libc::AF_NETLINK {
23873da5c369Sopenharmony_ci                return None;
23883da5c369Sopenharmony_ci            }
23893da5c369Sopenharmony_ci            Some(Self(ptr::read_unaligned(addr as *const _)))
23903da5c369Sopenharmony_ci        }
23913da5c369Sopenharmony_ci    }
23923da5c369Sopenharmony_ci
23933da5c369Sopenharmony_ci    impl AsRef<libc::sockaddr_nl> for NetlinkAddr {
23943da5c369Sopenharmony_ci        fn as_ref(&self) -> &libc::sockaddr_nl {
23953da5c369Sopenharmony_ci            &self.0
23963da5c369Sopenharmony_ci        }
23973da5c369Sopenharmony_ci    }
23983da5c369Sopenharmony_ci
23993da5c369Sopenharmony_ci    impl fmt::Display for NetlinkAddr {
24003da5c369Sopenharmony_ci        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24013da5c369Sopenharmony_ci            write!(f, "pid: {} groups: {}", self.pid(), self.groups())
24023da5c369Sopenharmony_ci        }
24033da5c369Sopenharmony_ci    }
24043da5c369Sopenharmony_ci}
24053da5c369Sopenharmony_ci
24063da5c369Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
24073da5c369Sopenharmony_ci#[cfg_attr(docsrs, doc(cfg(all())))]
24083da5c369Sopenharmony_cipub mod alg {
24093da5c369Sopenharmony_ci    use super::*;
24103da5c369Sopenharmony_ci    use libc::{c_char, sockaddr_alg, AF_ALG};
24113da5c369Sopenharmony_ci    use std::ffi::CStr;
24123da5c369Sopenharmony_ci    use std::hash::{Hash, Hasher};
24133da5c369Sopenharmony_ci    use std::{fmt, mem, str};
24143da5c369Sopenharmony_ci
24153da5c369Sopenharmony_ci    /// Socket address for the Linux kernel crypto API
24163da5c369Sopenharmony_ci    #[derive(Copy, Clone)]
24173da5c369Sopenharmony_ci    #[repr(transparent)]
24183da5c369Sopenharmony_ci    pub struct AlgAddr(pub(in super::super) sockaddr_alg);
24193da5c369Sopenharmony_ci
24203da5c369Sopenharmony_ci    impl private::SockaddrLikePriv for AlgAddr {}
24213da5c369Sopenharmony_ci    impl SockaddrLike for AlgAddr {
24223da5c369Sopenharmony_ci        unsafe fn from_raw(
24233da5c369Sopenharmony_ci            addr: *const libc::sockaddr,
24243da5c369Sopenharmony_ci            l: Option<libc::socklen_t>,
24253da5c369Sopenharmony_ci        ) -> Option<Self>
24263da5c369Sopenharmony_ci        where
24273da5c369Sopenharmony_ci            Self: Sized,
24283da5c369Sopenharmony_ci        {
24293da5c369Sopenharmony_ci            if let Some(l) = l {
24303da5c369Sopenharmony_ci                if l != mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t
24313da5c369Sopenharmony_ci                {
24323da5c369Sopenharmony_ci                    return None;
24333da5c369Sopenharmony_ci                }
24343da5c369Sopenharmony_ci            }
24353da5c369Sopenharmony_ci            if (*addr).sa_family as i32 != libc::AF_ALG {
24363da5c369Sopenharmony_ci                return None;
24373da5c369Sopenharmony_ci            }
24383da5c369Sopenharmony_ci            Some(Self(ptr::read_unaligned(addr as *const _)))
24393da5c369Sopenharmony_ci        }
24403da5c369Sopenharmony_ci    }
24413da5c369Sopenharmony_ci
24423da5c369Sopenharmony_ci    impl AsRef<libc::sockaddr_alg> for AlgAddr {
24433da5c369Sopenharmony_ci        fn as_ref(&self) -> &libc::sockaddr_alg {
24443da5c369Sopenharmony_ci            &self.0
24453da5c369Sopenharmony_ci        }
24463da5c369Sopenharmony_ci    }
24473da5c369Sopenharmony_ci
24483da5c369Sopenharmony_ci    // , PartialEq, Eq, Debug, Hash
24493da5c369Sopenharmony_ci    impl PartialEq for AlgAddr {
24503da5c369Sopenharmony_ci        fn eq(&self, other: &Self) -> bool {
24513da5c369Sopenharmony_ci            let (inner, other) = (self.0, other.0);
24523da5c369Sopenharmony_ci            (
24533da5c369Sopenharmony_ci                inner.salg_family,
24543da5c369Sopenharmony_ci                &inner.salg_type[..],
24553da5c369Sopenharmony_ci                inner.salg_feat,
24563da5c369Sopenharmony_ci                inner.salg_mask,
24573da5c369Sopenharmony_ci                &inner.salg_name[..],
24583da5c369Sopenharmony_ci            ) == (
24593da5c369Sopenharmony_ci                other.salg_family,
24603da5c369Sopenharmony_ci                &other.salg_type[..],
24613da5c369Sopenharmony_ci                other.salg_feat,
24623da5c369Sopenharmony_ci                other.salg_mask,
24633da5c369Sopenharmony_ci                &other.salg_name[..],
24643da5c369Sopenharmony_ci            )
24653da5c369Sopenharmony_ci        }
24663da5c369Sopenharmony_ci    }
24673da5c369Sopenharmony_ci
24683da5c369Sopenharmony_ci    impl Eq for AlgAddr {}
24693da5c369Sopenharmony_ci
24703da5c369Sopenharmony_ci    impl Hash for AlgAddr {
24713da5c369Sopenharmony_ci        fn hash<H: Hasher>(&self, s: &mut H) {
24723da5c369Sopenharmony_ci            let inner = self.0;
24733da5c369Sopenharmony_ci            (
24743da5c369Sopenharmony_ci                inner.salg_family,
24753da5c369Sopenharmony_ci                &inner.salg_type[..],
24763da5c369Sopenharmony_ci                inner.salg_feat,
24773da5c369Sopenharmony_ci                inner.salg_mask,
24783da5c369Sopenharmony_ci                &inner.salg_name[..],
24793da5c369Sopenharmony_ci            )
24803da5c369Sopenharmony_ci                .hash(s);
24813da5c369Sopenharmony_ci        }
24823da5c369Sopenharmony_ci    }
24833da5c369Sopenharmony_ci
24843da5c369Sopenharmony_ci    impl AlgAddr {
24853da5c369Sopenharmony_ci        /// Construct an `AF_ALG` socket from its cipher name and type.
24863da5c369Sopenharmony_ci        pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
24873da5c369Sopenharmony_ci            let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
24883da5c369Sopenharmony_ci            addr.salg_family = AF_ALG as u16;
24893da5c369Sopenharmony_ci            addr.salg_type[..alg_type.len()]
24903da5c369Sopenharmony_ci                .copy_from_slice(alg_type.to_string().as_bytes());
24913da5c369Sopenharmony_ci            addr.salg_name[..alg_name.len()]
24923da5c369Sopenharmony_ci                .copy_from_slice(alg_name.to_string().as_bytes());
24933da5c369Sopenharmony_ci
24943da5c369Sopenharmony_ci            AlgAddr(addr)
24953da5c369Sopenharmony_ci        }
24963da5c369Sopenharmony_ci
24973da5c369Sopenharmony_ci        /// Return the socket's cipher type, for example `hash` or `aead`.
24983da5c369Sopenharmony_ci        pub fn alg_type(&self) -> &CStr {
24993da5c369Sopenharmony_ci            unsafe {
25003da5c369Sopenharmony_ci                CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char)
25013da5c369Sopenharmony_ci            }
25023da5c369Sopenharmony_ci        }
25033da5c369Sopenharmony_ci
25043da5c369Sopenharmony_ci        /// Return the socket's cipher name, for example `sha1`.
25053da5c369Sopenharmony_ci        pub fn alg_name(&self) -> &CStr {
25063da5c369Sopenharmony_ci            unsafe {
25073da5c369Sopenharmony_ci                CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char)
25083da5c369Sopenharmony_ci            }
25093da5c369Sopenharmony_ci        }
25103da5c369Sopenharmony_ci    }
25113da5c369Sopenharmony_ci
25123da5c369Sopenharmony_ci    impl fmt::Display for AlgAddr {
25133da5c369Sopenharmony_ci        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25143da5c369Sopenharmony_ci            write!(
25153da5c369Sopenharmony_ci                f,
25163da5c369Sopenharmony_ci                "type: {} alg: {}",
25173da5c369Sopenharmony_ci                self.alg_name().to_string_lossy(),
25183da5c369Sopenharmony_ci                self.alg_type().to_string_lossy()
25193da5c369Sopenharmony_ci            )
25203da5c369Sopenharmony_ci        }
25213da5c369Sopenharmony_ci    }
25223da5c369Sopenharmony_ci
25233da5c369Sopenharmony_ci    impl fmt::Debug for AlgAddr {
25243da5c369Sopenharmony_ci        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25253da5c369Sopenharmony_ci            fmt::Display::fmt(self, f)
25263da5c369Sopenharmony_ci        }
25273da5c369Sopenharmony_ci    }
25283da5c369Sopenharmony_ci}
25293da5c369Sopenharmony_ci
25303da5c369Sopenharmony_cifeature! {
25313da5c369Sopenharmony_ci#![feature = "ioctl"]
25323da5c369Sopenharmony_ci#[cfg(any(target_os = "ios", target_os = "macos"))]
25333da5c369Sopenharmony_cipub mod sys_control {
25343da5c369Sopenharmony_ci    use crate::sys::socket::addr::AddressFamily;
25353da5c369Sopenharmony_ci    use libc::{self, c_uchar};
25363da5c369Sopenharmony_ci    use std::{fmt, mem, ptr};
25373da5c369Sopenharmony_ci    use std::os::unix::io::RawFd;
25383da5c369Sopenharmony_ci    use crate::{Errno, Result};
25393da5c369Sopenharmony_ci    use super::{private, SockaddrLike};
25403da5c369Sopenharmony_ci
25413da5c369Sopenharmony_ci    // FIXME: Move type into `libc`
25423da5c369Sopenharmony_ci    #[repr(C)]
25433da5c369Sopenharmony_ci    #[derive(Clone, Copy)]
25443da5c369Sopenharmony_ci    #[allow(missing_debug_implementations)]
25453da5c369Sopenharmony_ci    pub struct ctl_ioc_info {
25463da5c369Sopenharmony_ci        pub ctl_id: u32,
25473da5c369Sopenharmony_ci        pub ctl_name: [c_uchar; MAX_KCTL_NAME],
25483da5c369Sopenharmony_ci    }
25493da5c369Sopenharmony_ci
25503da5c369Sopenharmony_ci    const CTL_IOC_MAGIC: u8 = b'N';
25513da5c369Sopenharmony_ci    const CTL_IOC_INFO: u8 = 3;
25523da5c369Sopenharmony_ci    const MAX_KCTL_NAME: usize = 96;
25533da5c369Sopenharmony_ci
25543da5c369Sopenharmony_ci    ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info);
25553da5c369Sopenharmony_ci
25563da5c369Sopenharmony_ci    /// Apple system control socket
25573da5c369Sopenharmony_ci    ///
25583da5c369Sopenharmony_ci    /// # References
25593da5c369Sopenharmony_ci    ///
25603da5c369Sopenharmony_ci    /// <https://developer.apple.com/documentation/kernel/sockaddr_ctl>
25613da5c369Sopenharmony_ci    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
25623da5c369Sopenharmony_ci    #[repr(transparent)]
25633da5c369Sopenharmony_ci    pub struct SysControlAddr(pub(in super::super) libc::sockaddr_ctl);
25643da5c369Sopenharmony_ci
25653da5c369Sopenharmony_ci    impl private::SockaddrLikePriv for SysControlAddr {}
25663da5c369Sopenharmony_ci    impl SockaddrLike for SysControlAddr {
25673da5c369Sopenharmony_ci        unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
25683da5c369Sopenharmony_ci            -> Option<Self> where Self: Sized
25693da5c369Sopenharmony_ci        {
25703da5c369Sopenharmony_ci            if let Some(l) = len {
25713da5c369Sopenharmony_ci                if l != mem::size_of::<libc::sockaddr_ctl>() as libc::socklen_t {
25723da5c369Sopenharmony_ci                    return None;
25733da5c369Sopenharmony_ci                }
25743da5c369Sopenharmony_ci            }
25753da5c369Sopenharmony_ci            if (*addr).sa_family as i32 != libc::AF_SYSTEM {
25763da5c369Sopenharmony_ci                return None;
25773da5c369Sopenharmony_ci            }
25783da5c369Sopenharmony_ci            Some(Self(ptr::read_unaligned(addr as *const _)))
25793da5c369Sopenharmony_ci        }
25803da5c369Sopenharmony_ci    }
25813da5c369Sopenharmony_ci
25823da5c369Sopenharmony_ci    impl AsRef<libc::sockaddr_ctl> for SysControlAddr {
25833da5c369Sopenharmony_ci        fn as_ref(&self) -> &libc::sockaddr_ctl {
25843da5c369Sopenharmony_ci            &self.0
25853da5c369Sopenharmony_ci        }
25863da5c369Sopenharmony_ci    }
25873da5c369Sopenharmony_ci
25883da5c369Sopenharmony_ci    impl SysControlAddr {
25893da5c369Sopenharmony_ci        /// Construct a new `SysControlAddr` from its kernel unique identifier
25903da5c369Sopenharmony_ci        /// and unit number.
25913da5c369Sopenharmony_ci        pub const fn new(id: u32, unit: u32) -> SysControlAddr {
25923da5c369Sopenharmony_ci            let addr = libc::sockaddr_ctl {
25933da5c369Sopenharmony_ci                sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
25943da5c369Sopenharmony_ci                sc_family: AddressFamily::System as c_uchar,
25953da5c369Sopenharmony_ci                ss_sysaddr: libc::AF_SYS_CONTROL as u16,
25963da5c369Sopenharmony_ci                sc_id: id,
25973da5c369Sopenharmony_ci                sc_unit: unit,
25983da5c369Sopenharmony_ci                sc_reserved: [0; 5]
25993da5c369Sopenharmony_ci            };
26003da5c369Sopenharmony_ci
26013da5c369Sopenharmony_ci            SysControlAddr(addr)
26023da5c369Sopenharmony_ci        }
26033da5c369Sopenharmony_ci
26043da5c369Sopenharmony_ci        /// Construct a new `SysControlAddr` from its human readable name and
26053da5c369Sopenharmony_ci        /// unit number.
26063da5c369Sopenharmony_ci        pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
26073da5c369Sopenharmony_ci            if name.len() > MAX_KCTL_NAME {
26083da5c369Sopenharmony_ci                return Err(Errno::ENAMETOOLONG);
26093da5c369Sopenharmony_ci            }
26103da5c369Sopenharmony_ci
26113da5c369Sopenharmony_ci            let mut ctl_name = [0; MAX_KCTL_NAME];
26123da5c369Sopenharmony_ci            ctl_name[..name.len()].clone_from_slice(name.as_bytes());
26133da5c369Sopenharmony_ci            let mut info = ctl_ioc_info { ctl_id: 0, ctl_name };
26143da5c369Sopenharmony_ci
26153da5c369Sopenharmony_ci            unsafe { ctl_info(sockfd, &mut info)?; }
26163da5c369Sopenharmony_ci
26173da5c369Sopenharmony_ci            Ok(SysControlAddr::new(info.ctl_id, unit))
26183da5c369Sopenharmony_ci        }
26193da5c369Sopenharmony_ci
26203da5c369Sopenharmony_ci        /// Return the kernel unique identifier
26213da5c369Sopenharmony_ci        pub const fn id(&self) -> u32 {
26223da5c369Sopenharmony_ci            self.0.sc_id
26233da5c369Sopenharmony_ci        }
26243da5c369Sopenharmony_ci
26253da5c369Sopenharmony_ci        /// Return the kernel controller private unit number.
26263da5c369Sopenharmony_ci        pub const fn unit(&self) -> u32 {
26273da5c369Sopenharmony_ci            self.0.sc_unit
26283da5c369Sopenharmony_ci        }
26293da5c369Sopenharmony_ci    }
26303da5c369Sopenharmony_ci
26313da5c369Sopenharmony_ci    impl fmt::Display for SysControlAddr {
26323da5c369Sopenharmony_ci        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26333da5c369Sopenharmony_ci            fmt::Debug::fmt(self, f)
26343da5c369Sopenharmony_ci        }
26353da5c369Sopenharmony_ci    }
26363da5c369Sopenharmony_ci}
26373da5c369Sopenharmony_ci}
26383da5c369Sopenharmony_ci
26393da5c369Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
26403da5c369Sopenharmony_ci#[cfg_attr(docsrs, doc(cfg(all())))]
26413da5c369Sopenharmony_cimod datalink {
26423da5c369Sopenharmony_ci    feature! {
26433da5c369Sopenharmony_ci    #![feature = "net"]
26443da5c369Sopenharmony_ci    use super::{fmt, mem, private, ptr, SockaddrLike};
26453da5c369Sopenharmony_ci
26463da5c369Sopenharmony_ci    /// Hardware Address
26473da5c369Sopenharmony_ci    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
26483da5c369Sopenharmony_ci    #[repr(transparent)]
26493da5c369Sopenharmony_ci    pub struct LinkAddr(pub(in super::super) libc::sockaddr_ll);
26503da5c369Sopenharmony_ci
26513da5c369Sopenharmony_ci    impl LinkAddr {
26523da5c369Sopenharmony_ci        /// Physical-layer protocol
26533da5c369Sopenharmony_ci        pub fn protocol(&self) -> u16 {
26543da5c369Sopenharmony_ci            self.0.sll_protocol
26553da5c369Sopenharmony_ci        }
26563da5c369Sopenharmony_ci
26573da5c369Sopenharmony_ci        /// Interface number
26583da5c369Sopenharmony_ci        pub fn ifindex(&self) -> usize {
26593da5c369Sopenharmony_ci            self.0.sll_ifindex as usize
26603da5c369Sopenharmony_ci        }
26613da5c369Sopenharmony_ci
26623da5c369Sopenharmony_ci        /// ARP hardware type
26633da5c369Sopenharmony_ci        pub fn hatype(&self) -> u16 {
26643da5c369Sopenharmony_ci            self.0.sll_hatype
26653da5c369Sopenharmony_ci        }
26663da5c369Sopenharmony_ci
26673da5c369Sopenharmony_ci        /// Packet type
26683da5c369Sopenharmony_ci        pub fn pkttype(&self) -> u8 {
26693da5c369Sopenharmony_ci            self.0.sll_pkttype
26703da5c369Sopenharmony_ci        }
26713da5c369Sopenharmony_ci
26723da5c369Sopenharmony_ci        /// Length of MAC address
26733da5c369Sopenharmony_ci        pub fn halen(&self) -> usize {
26743da5c369Sopenharmony_ci            self.0.sll_halen as usize
26753da5c369Sopenharmony_ci        }
26763da5c369Sopenharmony_ci
26773da5c369Sopenharmony_ci        /// Physical-layer address (MAC)
26783da5c369Sopenharmony_ci        // Returns an Option just for cross-platform compatibility
26793da5c369Sopenharmony_ci        pub fn addr(&self) -> Option<[u8; 6]> {
26803da5c369Sopenharmony_ci            Some([
26813da5c369Sopenharmony_ci                self.0.sll_addr[0],
26823da5c369Sopenharmony_ci                self.0.sll_addr[1],
26833da5c369Sopenharmony_ci                self.0.sll_addr[2],
26843da5c369Sopenharmony_ci                self.0.sll_addr[3],
26853da5c369Sopenharmony_ci                self.0.sll_addr[4],
26863da5c369Sopenharmony_ci                self.0.sll_addr[5],
26873da5c369Sopenharmony_ci            ])
26883da5c369Sopenharmony_ci        }
26893da5c369Sopenharmony_ci    }
26903da5c369Sopenharmony_ci
26913da5c369Sopenharmony_ci    impl fmt::Display for LinkAddr {
26923da5c369Sopenharmony_ci        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26933da5c369Sopenharmony_ci            if let Some(addr) = self.addr() {
26943da5c369Sopenharmony_ci                write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
26953da5c369Sopenharmony_ci                    addr[0],
26963da5c369Sopenharmony_ci                    addr[1],
26973da5c369Sopenharmony_ci                    addr[2],
26983da5c369Sopenharmony_ci                    addr[3],
26993da5c369Sopenharmony_ci                    addr[4],
27003da5c369Sopenharmony_ci                    addr[5])
27013da5c369Sopenharmony_ci            } else {
27023da5c369Sopenharmony_ci                Ok(())
27033da5c369Sopenharmony_ci            }
27043da5c369Sopenharmony_ci        }
27053da5c369Sopenharmony_ci    }
27063da5c369Sopenharmony_ci    impl private::SockaddrLikePriv for LinkAddr {}
27073da5c369Sopenharmony_ci    impl SockaddrLike for LinkAddr {
27083da5c369Sopenharmony_ci        unsafe fn from_raw(addr: *const libc::sockaddr,
27093da5c369Sopenharmony_ci                           len: Option<libc::socklen_t>)
27103da5c369Sopenharmony_ci            -> Option<Self> where Self: Sized
27113da5c369Sopenharmony_ci        {
27123da5c369Sopenharmony_ci            if let Some(l) = len {
27133da5c369Sopenharmony_ci                if l != mem::size_of::<libc::sockaddr_ll>() as libc::socklen_t {
27143da5c369Sopenharmony_ci                    return None;
27153da5c369Sopenharmony_ci                }
27163da5c369Sopenharmony_ci            }
27173da5c369Sopenharmony_ci            if (*addr).sa_family as i32 != libc::AF_PACKET {
27183da5c369Sopenharmony_ci                return None;
27193da5c369Sopenharmony_ci            }
27203da5c369Sopenharmony_ci            Some(Self(ptr::read_unaligned(addr as *const _)))
27213da5c369Sopenharmony_ci        }
27223da5c369Sopenharmony_ci    }
27233da5c369Sopenharmony_ci
27243da5c369Sopenharmony_ci    impl AsRef<libc::sockaddr_ll> for LinkAddr {
27253da5c369Sopenharmony_ci        fn as_ref(&self) -> &libc::sockaddr_ll {
27263da5c369Sopenharmony_ci            &self.0
27273da5c369Sopenharmony_ci        }
27283da5c369Sopenharmony_ci    }
27293da5c369Sopenharmony_ci
27303da5c369Sopenharmony_ci    }
27313da5c369Sopenharmony_ci}
27323da5c369Sopenharmony_ci
27333da5c369Sopenharmony_ci#[cfg(any(
27343da5c369Sopenharmony_ci    target_os = "dragonfly",
27353da5c369Sopenharmony_ci    target_os = "freebsd",
27363da5c369Sopenharmony_ci    target_os = "ios",
27373da5c369Sopenharmony_ci    target_os = "macos",
27383da5c369Sopenharmony_ci    target_os = "illumos",
27393da5c369Sopenharmony_ci    target_os = "netbsd",
27403da5c369Sopenharmony_ci    target_os = "haiku",
27413da5c369Sopenharmony_ci    target_os = "openbsd"
27423da5c369Sopenharmony_ci))]
27433da5c369Sopenharmony_ci#[cfg_attr(docsrs, doc(cfg(all())))]
27443da5c369Sopenharmony_cimod datalink {
27453da5c369Sopenharmony_ci    feature! {
27463da5c369Sopenharmony_ci    #![feature = "net"]
27473da5c369Sopenharmony_ci    use super::{fmt, mem, private, ptr, SockaddrLike};
27483da5c369Sopenharmony_ci
27493da5c369Sopenharmony_ci    /// Hardware Address
27503da5c369Sopenharmony_ci    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
27513da5c369Sopenharmony_ci    #[repr(transparent)]
27523da5c369Sopenharmony_ci    pub struct LinkAddr(pub(in super::super) libc::sockaddr_dl);
27533da5c369Sopenharmony_ci
27543da5c369Sopenharmony_ci    impl LinkAddr {
27553da5c369Sopenharmony_ci        /// interface index, if != 0, system given index for interface
27563da5c369Sopenharmony_ci        #[cfg(not(target_os = "haiku"))]
27573da5c369Sopenharmony_ci        pub fn ifindex(&self) -> usize {
27583da5c369Sopenharmony_ci            self.0.sdl_index as usize
27593da5c369Sopenharmony_ci        }
27603da5c369Sopenharmony_ci
27613da5c369Sopenharmony_ci        /// Datalink type
27623da5c369Sopenharmony_ci        #[cfg(not(target_os = "haiku"))]
27633da5c369Sopenharmony_ci        pub fn datalink_type(&self) -> u8 {
27643da5c369Sopenharmony_ci            self.0.sdl_type
27653da5c369Sopenharmony_ci        }
27663da5c369Sopenharmony_ci
27673da5c369Sopenharmony_ci        /// MAC address start position
27683da5c369Sopenharmony_ci        pub fn nlen(&self) -> usize {
27693da5c369Sopenharmony_ci            self.0.sdl_nlen as usize
27703da5c369Sopenharmony_ci        }
27713da5c369Sopenharmony_ci
27723da5c369Sopenharmony_ci        /// link level address length
27733da5c369Sopenharmony_ci        pub fn alen(&self) -> usize {
27743da5c369Sopenharmony_ci            self.0.sdl_alen as usize
27753da5c369Sopenharmony_ci        }
27763da5c369Sopenharmony_ci
27773da5c369Sopenharmony_ci        /// link layer selector length
27783da5c369Sopenharmony_ci        #[cfg(not(target_os = "haiku"))]
27793da5c369Sopenharmony_ci        pub fn slen(&self) -> usize {
27803da5c369Sopenharmony_ci            self.0.sdl_slen as usize
27813da5c369Sopenharmony_ci        }
27823da5c369Sopenharmony_ci
27833da5c369Sopenharmony_ci        /// if link level address length == 0,
27843da5c369Sopenharmony_ci        /// or `sdl_data` not be larger.
27853da5c369Sopenharmony_ci        pub fn is_empty(&self) -> bool {
27863da5c369Sopenharmony_ci            let nlen = self.nlen();
27873da5c369Sopenharmony_ci            let alen = self.alen();
27883da5c369Sopenharmony_ci            let data_len = self.0.sdl_data.len();
27893da5c369Sopenharmony_ci
27903da5c369Sopenharmony_ci            alen == 0 || nlen + alen >= data_len
27913da5c369Sopenharmony_ci        }
27923da5c369Sopenharmony_ci
27933da5c369Sopenharmony_ci        /// Physical-layer address (MAC)
27943da5c369Sopenharmony_ci        // The cast is not unnecessary on all platforms.
27953da5c369Sopenharmony_ci        #[allow(clippy::unnecessary_cast)]
27963da5c369Sopenharmony_ci        pub fn addr(&self) -> Option<[u8; 6]> {
27973da5c369Sopenharmony_ci            let nlen = self.nlen();
27983da5c369Sopenharmony_ci            let data = self.0.sdl_data;
27993da5c369Sopenharmony_ci
28003da5c369Sopenharmony_ci            if self.is_empty() {
28013da5c369Sopenharmony_ci                None
28023da5c369Sopenharmony_ci            } else {
28033da5c369Sopenharmony_ci                Some([
28043da5c369Sopenharmony_ci                    data[nlen] as u8,
28053da5c369Sopenharmony_ci                    data[nlen + 1] as u8,
28063da5c369Sopenharmony_ci                    data[nlen + 2] as u8,
28073da5c369Sopenharmony_ci                    data[nlen + 3] as u8,
28083da5c369Sopenharmony_ci                    data[nlen + 4] as u8,
28093da5c369Sopenharmony_ci                    data[nlen + 5] as u8,
28103da5c369Sopenharmony_ci                ])
28113da5c369Sopenharmony_ci            }
28123da5c369Sopenharmony_ci        }
28133da5c369Sopenharmony_ci    }
28143da5c369Sopenharmony_ci
28153da5c369Sopenharmony_ci    impl fmt::Display for LinkAddr {
28163da5c369Sopenharmony_ci        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28173da5c369Sopenharmony_ci            if let Some(addr) = self.addr() {
28183da5c369Sopenharmony_ci                write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
28193da5c369Sopenharmony_ci                    addr[0],
28203da5c369Sopenharmony_ci                    addr[1],
28213da5c369Sopenharmony_ci                    addr[2],
28223da5c369Sopenharmony_ci                    addr[3],
28233da5c369Sopenharmony_ci                    addr[4],
28243da5c369Sopenharmony_ci                    addr[5])
28253da5c369Sopenharmony_ci            } else {
28263da5c369Sopenharmony_ci                Ok(())
28273da5c369Sopenharmony_ci            }
28283da5c369Sopenharmony_ci        }
28293da5c369Sopenharmony_ci    }
28303da5c369Sopenharmony_ci    impl private::SockaddrLikePriv for LinkAddr {}
28313da5c369Sopenharmony_ci    impl SockaddrLike for LinkAddr {
28323da5c369Sopenharmony_ci        unsafe fn from_raw(addr: *const libc::sockaddr,
28333da5c369Sopenharmony_ci                           len: Option<libc::socklen_t>)
28343da5c369Sopenharmony_ci            -> Option<Self> where Self: Sized
28353da5c369Sopenharmony_ci        {
28363da5c369Sopenharmony_ci            if let Some(l) = len {
28373da5c369Sopenharmony_ci                if l != mem::size_of::<libc::sockaddr_dl>() as libc::socklen_t {
28383da5c369Sopenharmony_ci                    return None;
28393da5c369Sopenharmony_ci                }
28403da5c369Sopenharmony_ci            }
28413da5c369Sopenharmony_ci            if (*addr).sa_family as i32 != libc::AF_LINK {
28423da5c369Sopenharmony_ci                return None;
28433da5c369Sopenharmony_ci            }
28443da5c369Sopenharmony_ci            Some(Self(ptr::read_unaligned(addr as *const _)))
28453da5c369Sopenharmony_ci        }
28463da5c369Sopenharmony_ci    }
28473da5c369Sopenharmony_ci
28483da5c369Sopenharmony_ci    impl AsRef<libc::sockaddr_dl> for LinkAddr {
28493da5c369Sopenharmony_ci        fn as_ref(&self) -> &libc::sockaddr_dl {
28503da5c369Sopenharmony_ci            &self.0
28513da5c369Sopenharmony_ci        }
28523da5c369Sopenharmony_ci    }
28533da5c369Sopenharmony_ci
28543da5c369Sopenharmony_ci    }
28553da5c369Sopenharmony_ci}
28563da5c369Sopenharmony_ci
28573da5c369Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
28583da5c369Sopenharmony_ci#[cfg_attr(docsrs, doc(cfg(all())))]
28593da5c369Sopenharmony_cipub mod vsock {
28603da5c369Sopenharmony_ci    use super::*;
28613da5c369Sopenharmony_ci    use crate::sys::socket::addr::AddressFamily;
28623da5c369Sopenharmony_ci    use libc::{sa_family_t, sockaddr_vm};
28633da5c369Sopenharmony_ci    use std::hash::{Hash, Hasher};
28643da5c369Sopenharmony_ci    use std::{fmt, mem};
28653da5c369Sopenharmony_ci
28663da5c369Sopenharmony_ci    /// Socket address for VMWare VSockets protocol
28673da5c369Sopenharmony_ci    ///
28683da5c369Sopenharmony_ci    /// # References
28693da5c369Sopenharmony_ci    ///
28703da5c369Sopenharmony_ci    /// [vsock(7)](https://man7.org/linux/man-pages/man7/vsock.7.html)
28713da5c369Sopenharmony_ci    #[derive(Copy, Clone)]
28723da5c369Sopenharmony_ci    #[repr(transparent)]
28733da5c369Sopenharmony_ci    pub struct VsockAddr(pub(in super::super) sockaddr_vm);
28743da5c369Sopenharmony_ci
28753da5c369Sopenharmony_ci    impl private::SockaddrLikePriv for VsockAddr {}
28763da5c369Sopenharmony_ci    impl SockaddrLike for VsockAddr {
28773da5c369Sopenharmony_ci        unsafe fn from_raw(
28783da5c369Sopenharmony_ci            addr: *const libc::sockaddr,
28793da5c369Sopenharmony_ci            len: Option<libc::socklen_t>,
28803da5c369Sopenharmony_ci        ) -> Option<Self>
28813da5c369Sopenharmony_ci        where
28823da5c369Sopenharmony_ci            Self: Sized,
28833da5c369Sopenharmony_ci        {
28843da5c369Sopenharmony_ci            if let Some(l) = len {
28853da5c369Sopenharmony_ci                if l != mem::size_of::<libc::sockaddr_vm>() as libc::socklen_t {
28863da5c369Sopenharmony_ci                    return None;
28873da5c369Sopenharmony_ci                }
28883da5c369Sopenharmony_ci            }
28893da5c369Sopenharmony_ci            if (*addr).sa_family as i32 != libc::AF_VSOCK {
28903da5c369Sopenharmony_ci                return None;
28913da5c369Sopenharmony_ci            }
28923da5c369Sopenharmony_ci            Some(Self(ptr::read_unaligned(addr as *const _)))
28933da5c369Sopenharmony_ci        }
28943da5c369Sopenharmony_ci    }
28953da5c369Sopenharmony_ci
28963da5c369Sopenharmony_ci    impl AsRef<libc::sockaddr_vm> for VsockAddr {
28973da5c369Sopenharmony_ci        fn as_ref(&self) -> &libc::sockaddr_vm {
28983da5c369Sopenharmony_ci            &self.0
28993da5c369Sopenharmony_ci        }
29003da5c369Sopenharmony_ci    }
29013da5c369Sopenharmony_ci
29023da5c369Sopenharmony_ci    impl PartialEq for VsockAddr {
29033da5c369Sopenharmony_ci        fn eq(&self, other: &Self) -> bool {
29043da5c369Sopenharmony_ci            let (inner, other) = (self.0, other.0);
29053da5c369Sopenharmony_ci            (inner.svm_family, inner.svm_cid, inner.svm_port)
29063da5c369Sopenharmony_ci                == (other.svm_family, other.svm_cid, other.svm_port)
29073da5c369Sopenharmony_ci        }
29083da5c369Sopenharmony_ci    }
29093da5c369Sopenharmony_ci
29103da5c369Sopenharmony_ci    impl Eq for VsockAddr {}
29113da5c369Sopenharmony_ci
29123da5c369Sopenharmony_ci    impl Hash for VsockAddr {
29133da5c369Sopenharmony_ci        fn hash<H: Hasher>(&self, s: &mut H) {
29143da5c369Sopenharmony_ci            let inner = self.0;
29153da5c369Sopenharmony_ci            (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
29163da5c369Sopenharmony_ci        }
29173da5c369Sopenharmony_ci    }
29183da5c369Sopenharmony_ci
29193da5c369Sopenharmony_ci    /// VSOCK Address
29203da5c369Sopenharmony_ci    ///
29213da5c369Sopenharmony_ci    /// The address for AF_VSOCK socket is defined as a combination of a
29223da5c369Sopenharmony_ci    /// 32-bit Context Identifier (CID) and a 32-bit port number.
29233da5c369Sopenharmony_ci    impl VsockAddr {
29243da5c369Sopenharmony_ci        /// Construct a `VsockAddr` from its raw fields.
29253da5c369Sopenharmony_ci        pub fn new(cid: u32, port: u32) -> VsockAddr {
29263da5c369Sopenharmony_ci            let mut addr: sockaddr_vm = unsafe { mem::zeroed() };
29273da5c369Sopenharmony_ci            addr.svm_family = AddressFamily::Vsock as sa_family_t;
29283da5c369Sopenharmony_ci            addr.svm_cid = cid;
29293da5c369Sopenharmony_ci            addr.svm_port = port;
29303da5c369Sopenharmony_ci
29313da5c369Sopenharmony_ci            VsockAddr(addr)
29323da5c369Sopenharmony_ci        }
29333da5c369Sopenharmony_ci
29343da5c369Sopenharmony_ci        /// Context Identifier (CID)
29353da5c369Sopenharmony_ci        pub fn cid(&self) -> u32 {
29363da5c369Sopenharmony_ci            self.0.svm_cid
29373da5c369Sopenharmony_ci        }
29383da5c369Sopenharmony_ci
29393da5c369Sopenharmony_ci        /// Port number
29403da5c369Sopenharmony_ci        pub fn port(&self) -> u32 {
29413da5c369Sopenharmony_ci            self.0.svm_port
29423da5c369Sopenharmony_ci        }
29433da5c369Sopenharmony_ci    }
29443da5c369Sopenharmony_ci
29453da5c369Sopenharmony_ci    impl fmt::Display for VsockAddr {
29463da5c369Sopenharmony_ci        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
29473da5c369Sopenharmony_ci            write!(f, "cid: {} port: {}", self.cid(), self.port())
29483da5c369Sopenharmony_ci        }
29493da5c369Sopenharmony_ci    }
29503da5c369Sopenharmony_ci
29513da5c369Sopenharmony_ci    impl fmt::Debug for VsockAddr {
29523da5c369Sopenharmony_ci        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
29533da5c369Sopenharmony_ci            fmt::Display::fmt(self, f)
29543da5c369Sopenharmony_ci        }
29553da5c369Sopenharmony_ci    }
29563da5c369Sopenharmony_ci}
29573da5c369Sopenharmony_ci
29583da5c369Sopenharmony_ci#[cfg(test)]
29593da5c369Sopenharmony_cimod tests {
29603da5c369Sopenharmony_ci    use super::*;
29613da5c369Sopenharmony_ci
29623da5c369Sopenharmony_ci    mod types {
29633da5c369Sopenharmony_ci        use super::*;
29643da5c369Sopenharmony_ci
29653da5c369Sopenharmony_ci        #[test]
29663da5c369Sopenharmony_ci        fn test_ipv4addr_to_libc() {
29673da5c369Sopenharmony_ci            let s = std::net::Ipv4Addr::new(1, 2, 3, 4);
29683da5c369Sopenharmony_ci            let l = ipv4addr_to_libc(s);
29693da5c369Sopenharmony_ci            assert_eq!(l.s_addr, u32::to_be(0x01020304));
29703da5c369Sopenharmony_ci        }
29713da5c369Sopenharmony_ci
29723da5c369Sopenharmony_ci        #[test]
29733da5c369Sopenharmony_ci        fn test_ipv6addr_to_libc() {
29743da5c369Sopenharmony_ci            let s = std::net::Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8);
29753da5c369Sopenharmony_ci            let l = ipv6addr_to_libc(&s);
29763da5c369Sopenharmony_ci            assert_eq!(
29773da5c369Sopenharmony_ci                l.s6_addr,
29783da5c369Sopenharmony_ci                [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8]
29793da5c369Sopenharmony_ci            );
29803da5c369Sopenharmony_ci        }
29813da5c369Sopenharmony_ci    }
29823da5c369Sopenharmony_ci
29833da5c369Sopenharmony_ci    mod link {
29843da5c369Sopenharmony_ci        #![allow(clippy::cast_ptr_alignment)]
29853da5c369Sopenharmony_ci
29863da5c369Sopenharmony_ci        #[cfg(any(
29873da5c369Sopenharmony_ci            target_os = "ios",
29883da5c369Sopenharmony_ci            target_os = "macos",
29893da5c369Sopenharmony_ci            target_os = "illumos"
29903da5c369Sopenharmony_ci        ))]
29913da5c369Sopenharmony_ci        use super::super::super::socklen_t;
29923da5c369Sopenharmony_ci        use super::*;
29933da5c369Sopenharmony_ci
29943da5c369Sopenharmony_ci        /// Don't panic when trying to display an empty datalink address
29953da5c369Sopenharmony_ci        #[cfg(any(
29963da5c369Sopenharmony_ci            target_os = "dragonfly",
29973da5c369Sopenharmony_ci            target_os = "freebsd",
29983da5c369Sopenharmony_ci            target_os = "ios",
29993da5c369Sopenharmony_ci            target_os = "macos",
30003da5c369Sopenharmony_ci            target_os = "netbsd",
30013da5c369Sopenharmony_ci            target_os = "openbsd"
30023da5c369Sopenharmony_ci        ))]
30033da5c369Sopenharmony_ci        #[test]
30043da5c369Sopenharmony_ci        fn test_datalink_display() {
30053da5c369Sopenharmony_ci            use super::super::LinkAddr;
30063da5c369Sopenharmony_ci            use std::mem;
30073da5c369Sopenharmony_ci
30083da5c369Sopenharmony_ci            let la = LinkAddr(libc::sockaddr_dl {
30093da5c369Sopenharmony_ci                sdl_len: 56,
30103da5c369Sopenharmony_ci                sdl_family: 18,
30113da5c369Sopenharmony_ci                sdl_index: 5,
30123da5c369Sopenharmony_ci                sdl_type: 24,
30133da5c369Sopenharmony_ci                sdl_nlen: 3,
30143da5c369Sopenharmony_ci                sdl_alen: 0,
30153da5c369Sopenharmony_ci                sdl_slen: 0,
30163da5c369Sopenharmony_ci                ..unsafe { mem::zeroed() }
30173da5c369Sopenharmony_ci            });
30183da5c369Sopenharmony_ci            format!("{}", la);
30193da5c369Sopenharmony_ci        }
30203da5c369Sopenharmony_ci
30213da5c369Sopenharmony_ci        #[cfg(all(
30223da5c369Sopenharmony_ci            any(
30233da5c369Sopenharmony_ci                target_os = "android",
30243da5c369Sopenharmony_ci                target_os = "fuchsia",
30253da5c369Sopenharmony_ci                target_os = "linux"
30263da5c369Sopenharmony_ci            ),
30273da5c369Sopenharmony_ci            target_endian = "little"
30283da5c369Sopenharmony_ci        ))]
30293da5c369Sopenharmony_ci        #[test]
30303da5c369Sopenharmony_ci        fn linux_loopback() {
30313da5c369Sopenharmony_ci            #[repr(align(2))]
30323da5c369Sopenharmony_ci            struct Raw([u8; 20]);
30333da5c369Sopenharmony_ci
30343da5c369Sopenharmony_ci            let bytes = Raw([
30353da5c369Sopenharmony_ci                17u8, 0, 0, 0, 1, 0, 0, 0, 4, 3, 0, 6, 1, 2, 3, 4, 5, 6, 0, 0,
30363da5c369Sopenharmony_ci            ]);
30373da5c369Sopenharmony_ci            let sa = bytes.0.as_ptr() as *const libc::sockaddr;
30383da5c369Sopenharmony_ci            let len = None;
30393da5c369Sopenharmony_ci            let sock_addr =
30403da5c369Sopenharmony_ci                unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
30413da5c369Sopenharmony_ci            assert_eq!(sock_addr.family(), Some(AddressFamily::Packet));
30423da5c369Sopenharmony_ci            match sock_addr.as_link_addr() {
30433da5c369Sopenharmony_ci                Some(dl) => assert_eq!(dl.addr(), Some([1, 2, 3, 4, 5, 6])),
30443da5c369Sopenharmony_ci                None => panic!("Can't unwrap sockaddr storage"),
30453da5c369Sopenharmony_ci            }
30463da5c369Sopenharmony_ci        }
30473da5c369Sopenharmony_ci
30483da5c369Sopenharmony_ci        #[cfg(any(target_os = "ios", target_os = "macos"))]
30493da5c369Sopenharmony_ci        #[test]
30503da5c369Sopenharmony_ci        fn macos_loopback() {
30513da5c369Sopenharmony_ci            let bytes =
30523da5c369Sopenharmony_ci                [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
30533da5c369Sopenharmony_ci            let sa = bytes.as_ptr() as *const libc::sockaddr;
30543da5c369Sopenharmony_ci            let len = Some(bytes.len() as socklen_t);
30553da5c369Sopenharmony_ci            let sock_addr =
30563da5c369Sopenharmony_ci                unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
30573da5c369Sopenharmony_ci            assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
30583da5c369Sopenharmony_ci            match sock_addr.as_link_addr() {
30593da5c369Sopenharmony_ci                Some(dl) => {
30603da5c369Sopenharmony_ci                    assert!(dl.addr().is_none());
30613da5c369Sopenharmony_ci                }
30623da5c369Sopenharmony_ci                None => panic!("Can't unwrap sockaddr storage"),
30633da5c369Sopenharmony_ci            }
30643da5c369Sopenharmony_ci        }
30653da5c369Sopenharmony_ci
30663da5c369Sopenharmony_ci        #[cfg(any(target_os = "ios", target_os = "macos"))]
30673da5c369Sopenharmony_ci        #[test]
30683da5c369Sopenharmony_ci        fn macos_tap() {
30693da5c369Sopenharmony_ci            let bytes = [
30703da5c369Sopenharmony_ci                20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35,
30713da5c369Sopenharmony_ci                76, -80,
30723da5c369Sopenharmony_ci            ];
30733da5c369Sopenharmony_ci            let ptr = bytes.as_ptr();
30743da5c369Sopenharmony_ci            let sa = ptr as *const libc::sockaddr;
30753da5c369Sopenharmony_ci            let len = Some(bytes.len() as socklen_t);
30763da5c369Sopenharmony_ci
30773da5c369Sopenharmony_ci            let sock_addr =
30783da5c369Sopenharmony_ci                unsafe { SockaddrStorage::from_raw(sa, len).unwrap() };
30793da5c369Sopenharmony_ci            assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
30803da5c369Sopenharmony_ci            match sock_addr.as_link_addr() {
30813da5c369Sopenharmony_ci                Some(dl) => {
30823da5c369Sopenharmony_ci                    assert_eq!(dl.addr(), Some([24u8, 101, 144, 221, 76, 176]))
30833da5c369Sopenharmony_ci                }
30843da5c369Sopenharmony_ci                None => panic!("Can't unwrap sockaddr storage"),
30853da5c369Sopenharmony_ci            }
30863da5c369Sopenharmony_ci        }
30873da5c369Sopenharmony_ci
30883da5c369Sopenharmony_ci        #[cfg(target_os = "illumos")]
30893da5c369Sopenharmony_ci        #[test]
30903da5c369Sopenharmony_ci        fn illumos_tap() {
30913da5c369Sopenharmony_ci            let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176];
30923da5c369Sopenharmony_ci            let ptr = bytes.as_ptr();
30933da5c369Sopenharmony_ci            let sa = ptr as *const libc::sockaddr;
30943da5c369Sopenharmony_ci            let len = Some(bytes.len() as socklen_t);
30953da5c369Sopenharmony_ci            let _sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) };
30963da5c369Sopenharmony_ci
30973da5c369Sopenharmony_ci            assert!(_sock_addr.is_some());
30983da5c369Sopenharmony_ci
30993da5c369Sopenharmony_ci            let sock_addr = _sock_addr.unwrap();
31003da5c369Sopenharmony_ci
31013da5c369Sopenharmony_ci            assert_eq!(sock_addr.family().unwrap(), AddressFamily::Link);
31023da5c369Sopenharmony_ci
31033da5c369Sopenharmony_ci            assert_eq!(
31043da5c369Sopenharmony_ci                sock_addr.as_link_addr().unwrap().addr(),
31053da5c369Sopenharmony_ci                Some([24u8, 101, 144, 221, 76, 176])
31063da5c369Sopenharmony_ci            );
31073da5c369Sopenharmony_ci        }
31083da5c369Sopenharmony_ci
31093da5c369Sopenharmony_ci        #[test]
31103da5c369Sopenharmony_ci        fn size() {
31113da5c369Sopenharmony_ci            #[cfg(any(
31123da5c369Sopenharmony_ci                target_os = "dragonfly",
31133da5c369Sopenharmony_ci                target_os = "freebsd",
31143da5c369Sopenharmony_ci                target_os = "ios",
31153da5c369Sopenharmony_ci                target_os = "macos",
31163da5c369Sopenharmony_ci                target_os = "netbsd",
31173da5c369Sopenharmony_ci                target_os = "illumos",
31183da5c369Sopenharmony_ci                target_os = "openbsd",
31193da5c369Sopenharmony_ci                target_os = "haiku"
31203da5c369Sopenharmony_ci            ))]
31213da5c369Sopenharmony_ci            let l = mem::size_of::<libc::sockaddr_dl>();
31223da5c369Sopenharmony_ci            #[cfg(any(
31233da5c369Sopenharmony_ci                target_os = "android",
31243da5c369Sopenharmony_ci                target_os = "fuchsia",
31253da5c369Sopenharmony_ci                target_os = "linux"
31263da5c369Sopenharmony_ci            ))]
31273da5c369Sopenharmony_ci            let l = mem::size_of::<libc::sockaddr_ll>();
31283da5c369Sopenharmony_ci            assert_eq!(LinkAddr::size() as usize, l);
31293da5c369Sopenharmony_ci        }
31303da5c369Sopenharmony_ci    }
31313da5c369Sopenharmony_ci
31323da5c369Sopenharmony_ci    mod sockaddr_in {
31333da5c369Sopenharmony_ci        use super::*;
31343da5c369Sopenharmony_ci        use std::str::FromStr;
31353da5c369Sopenharmony_ci
31363da5c369Sopenharmony_ci        #[test]
31373da5c369Sopenharmony_ci        fn display() {
31383da5c369Sopenharmony_ci            let s = "127.0.0.1:8080";
31393da5c369Sopenharmony_ci            let addr = SockaddrIn::from_str(s).unwrap();
31403da5c369Sopenharmony_ci            assert_eq!(s, format!("{}", addr));
31413da5c369Sopenharmony_ci        }
31423da5c369Sopenharmony_ci
31433da5c369Sopenharmony_ci        #[test]
31443da5c369Sopenharmony_ci        fn size() {
31453da5c369Sopenharmony_ci            assert_eq!(
31463da5c369Sopenharmony_ci                mem::size_of::<libc::sockaddr_in>(),
31473da5c369Sopenharmony_ci                SockaddrIn::size() as usize
31483da5c369Sopenharmony_ci            );
31493da5c369Sopenharmony_ci        }
31503da5c369Sopenharmony_ci    }
31513da5c369Sopenharmony_ci
31523da5c369Sopenharmony_ci    mod sockaddr_in6 {
31533da5c369Sopenharmony_ci        use super::*;
31543da5c369Sopenharmony_ci        use std::str::FromStr;
31553da5c369Sopenharmony_ci
31563da5c369Sopenharmony_ci        #[test]
31573da5c369Sopenharmony_ci        fn display() {
31583da5c369Sopenharmony_ci            let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
31593da5c369Sopenharmony_ci            let addr = SockaddrIn6::from_str(s).unwrap();
31603da5c369Sopenharmony_ci            assert_eq!(s, format!("{}", addr));
31613da5c369Sopenharmony_ci        }
31623da5c369Sopenharmony_ci
31633da5c369Sopenharmony_ci        #[test]
31643da5c369Sopenharmony_ci        fn size() {
31653da5c369Sopenharmony_ci            assert_eq!(
31663da5c369Sopenharmony_ci                mem::size_of::<libc::sockaddr_in6>(),
31673da5c369Sopenharmony_ci                SockaddrIn6::size() as usize
31683da5c369Sopenharmony_ci            );
31693da5c369Sopenharmony_ci        }
31703da5c369Sopenharmony_ci
31713da5c369Sopenharmony_ci        #[test]
31723da5c369Sopenharmony_ci        // Ensure that we can convert to-and-from std::net variants without change.
31733da5c369Sopenharmony_ci        fn to_and_from() {
31743da5c369Sopenharmony_ci            let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
31753da5c369Sopenharmony_ci            let mut nix_sin6 = SockaddrIn6::from_str(s).unwrap();
31763da5c369Sopenharmony_ci            nix_sin6.0.sin6_flowinfo = 0x12345678;
31773da5c369Sopenharmony_ci            nix_sin6.0.sin6_scope_id = 0x9abcdef0;
31783da5c369Sopenharmony_ci
31793da5c369Sopenharmony_ci            let std_sin6 : std::net::SocketAddrV6 = nix_sin6.into();
31803da5c369Sopenharmony_ci            assert_eq!(nix_sin6, std_sin6.into());
31813da5c369Sopenharmony_ci        }
31823da5c369Sopenharmony_ci    }
31833da5c369Sopenharmony_ci
31843da5c369Sopenharmony_ci    mod sockaddr_storage {
31853da5c369Sopenharmony_ci        use super::*;
31863da5c369Sopenharmony_ci
31873da5c369Sopenharmony_ci        #[test]
31883da5c369Sopenharmony_ci        fn from_sockaddr_un_named() {
31893da5c369Sopenharmony_ci            let ua = UnixAddr::new("/var/run/mysock").unwrap();
31903da5c369Sopenharmony_ci            let ptr = ua.as_ptr() as *const libc::sockaddr;
31913da5c369Sopenharmony_ci            let ss = unsafe {
31923da5c369Sopenharmony_ci                SockaddrStorage::from_raw(ptr, Some(ua.len()))
31933da5c369Sopenharmony_ci            }.unwrap();
31943da5c369Sopenharmony_ci            assert_eq!(ss.len(), ua.len());
31953da5c369Sopenharmony_ci        }
31963da5c369Sopenharmony_ci
31973da5c369Sopenharmony_ci        #[cfg(any(target_os = "android", target_os = "linux"))]
31983da5c369Sopenharmony_ci        #[test]
31993da5c369Sopenharmony_ci        fn from_sockaddr_un_abstract_named() {
32003da5c369Sopenharmony_ci            let name = String::from("nix\0abstract\0test");
32013da5c369Sopenharmony_ci            let ua = UnixAddr::new_abstract(name.as_bytes()).unwrap();
32023da5c369Sopenharmony_ci            let ptr = ua.as_ptr() as *const libc::sockaddr;
32033da5c369Sopenharmony_ci            let ss = unsafe {
32043da5c369Sopenharmony_ci                SockaddrStorage::from_raw(ptr, Some(ua.len()))
32053da5c369Sopenharmony_ci            }.unwrap();
32063da5c369Sopenharmony_ci            assert_eq!(ss.len(), ua.len());
32073da5c369Sopenharmony_ci        }
32083da5c369Sopenharmony_ci
32093da5c369Sopenharmony_ci        #[cfg(any(target_os = "android", target_os = "linux"))]
32103da5c369Sopenharmony_ci        #[test]
32113da5c369Sopenharmony_ci        fn from_sockaddr_un_abstract_unnamed() {
32123da5c369Sopenharmony_ci            let ua = UnixAddr::new_unnamed();
32133da5c369Sopenharmony_ci            let ptr = ua.as_ptr() as *const libc::sockaddr;
32143da5c369Sopenharmony_ci            let ss = unsafe {
32153da5c369Sopenharmony_ci                SockaddrStorage::from_raw(ptr, Some(ua.len()))
32163da5c369Sopenharmony_ci            }.unwrap();
32173da5c369Sopenharmony_ci            assert_eq!(ss.len(), ua.len());
32183da5c369Sopenharmony_ci        }
32193da5c369Sopenharmony_ci    }
32203da5c369Sopenharmony_ci
32213da5c369Sopenharmony_ci    mod unixaddr {
32223da5c369Sopenharmony_ci        use super::*;
32233da5c369Sopenharmony_ci
32243da5c369Sopenharmony_ci        #[cfg(any(target_os = "android", target_os = "linux"))]
32253da5c369Sopenharmony_ci        #[test]
32263da5c369Sopenharmony_ci        fn abstract_sun_path() {
32273da5c369Sopenharmony_ci            let name = String::from("nix\0abstract\0test");
32283da5c369Sopenharmony_ci            let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
32293da5c369Sopenharmony_ci
32303da5c369Sopenharmony_ci            let sun_path1 =
32313da5c369Sopenharmony_ci                unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] };
32323da5c369Sopenharmony_ci            let sun_path2 = [
32333da5c369Sopenharmony_ci                0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0,
32343da5c369Sopenharmony_ci                116, 101, 115, 116,
32353da5c369Sopenharmony_ci            ];
32363da5c369Sopenharmony_ci            assert_eq!(sun_path1, sun_path2);
32373da5c369Sopenharmony_ci        }
32383da5c369Sopenharmony_ci
32393da5c369Sopenharmony_ci        #[test]
32403da5c369Sopenharmony_ci        fn size() {
32413da5c369Sopenharmony_ci            assert_eq!(
32423da5c369Sopenharmony_ci                mem::size_of::<libc::sockaddr_un>(),
32433da5c369Sopenharmony_ci                UnixAddr::size() as usize
32443da5c369Sopenharmony_ci            );
32453da5c369Sopenharmony_ci        }
32463da5c369Sopenharmony_ci    }
32473da5c369Sopenharmony_ci}
3248