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