nix/sys/socket/
addr.rs

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