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