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