1 use super::sa_family_t;
2 use crate::{Result, NixPath};
3 use crate::errno::Errno;
4 use memoffset::offset_of;
5 use std::{fmt, mem, net, ptr, slice};
6 use std::ffi::OsStr;
7 use std::hash::{Hash, Hasher};
8 use std::path::Path;
9 use std::os::unix::ffi::OsStrExt;
10 #[cfg(any(target_os = "android", target_os = "linux"))]
11 use crate::sys::socket::addr::netlink::NetlinkAddr;
12 #[cfg(any(target_os = "android", target_os = "linux"))]
13 use crate::sys::socket::addr::alg::AlgAddr;
14 #[cfg(any(target_os = "ios", target_os = "macos"))]
15 use std::os::unix::io::RawFd;
16 #[cfg(any(target_os = "ios", target_os = "macos"))]
17 use crate::sys::socket::addr::sys_control::SysControlAddr;
18 #[cfg(any(target_os = "android",
19           target_os = "dragonfly",
20           target_os = "freebsd",
21           target_os = "ios",
22           target_os = "linux",
23           target_os = "macos",
24           target_os = "illumos",
25           target_os = "netbsd",
26           target_os = "openbsd",
27           target_os = "fuchsia"))]
28 pub use self::datalink::LinkAddr;
29 #[cfg(any(target_os = "android", target_os = "linux"))]
30 pub use self::vsock::VsockAddr;
31 
32 /// These constants specify the protocol family to be used
33 /// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
34 #[repr(i32)]
35 #[non_exhaustive]
36 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
37 pub enum AddressFamily {
38     /// Local communication (see [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html))
39     Unix = libc::AF_UNIX,
40     /// IPv4 Internet protocols (see [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html))
41     Inet = libc::AF_INET,
42     /// IPv6 Internet protocols (see [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html))
43     Inet6 = libc::AF_INET6,
44     /// Kernel user interface device (see [`netlink(7)`](https://man7.org/linux/man-pages/man7/netlink.7.html))
45     #[cfg(any(target_os = "android", target_os = "linux"))]
46     Netlink = libc::AF_NETLINK,
47     /// Low level packet interface (see [`packet(7)`](https://man7.org/linux/man-pages/man7/packet.7.html))
48     #[cfg(any(target_os = "android",
49               target_os = "linux",
50               target_os = "illumos",
51               target_os = "fuchsia",
52               target_os = "solaris"))]
53     Packet = libc::AF_PACKET,
54     /// KEXT Controls and Notifications
55     #[cfg(any(target_os = "ios", target_os = "macos"))]
56     System = libc::AF_SYSTEM,
57     /// Amateur radio AX.25 protocol
58     #[cfg(any(target_os = "android", target_os = "linux"))]
59     Ax25 = libc::AF_AX25,
60     /// IPX - Novell protocols
61     Ipx = libc::AF_IPX,
62     /// AppleTalk
63     AppleTalk = libc::AF_APPLETALK,
64     #[cfg(any(target_os = "android", target_os = "linux"))]
65     NetRom = libc::AF_NETROM,
66     #[cfg(any(target_os = "android", target_os = "linux"))]
67     Bridge = libc::AF_BRIDGE,
68     /// Access to raw ATM PVCs
69     #[cfg(any(target_os = "android", target_os = "linux"))]
70     AtmPvc = libc::AF_ATMPVC,
71     /// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](https://man7.org/linux/man-pages/man7/x25.7.html))
72     #[cfg(any(target_os = "android", target_os = "linux"))]
73     X25 = libc::AF_X25,
74     #[cfg(any(target_os = "android", target_os = "linux"))]
75     Rose = libc::AF_ROSE,
76     Decnet = libc::AF_DECnet,
77     #[cfg(any(target_os = "android", target_os = "linux"))]
78     NetBeui = libc::AF_NETBEUI,
79     #[cfg(any(target_os = "android", target_os = "linux"))]
80     Security = libc::AF_SECURITY,
81     #[cfg(any(target_os = "android", target_os = "linux"))]
82     Key = libc::AF_KEY,
83     #[cfg(any(target_os = "android", target_os = "linux"))]
84     Ash = libc::AF_ASH,
85     #[cfg(any(target_os = "android", target_os = "linux"))]
86     Econet = libc::AF_ECONET,
87     #[cfg(any(target_os = "android", target_os = "linux"))]
88     AtmSvc = libc::AF_ATMSVC,
89     #[cfg(any(target_os = "android", target_os = "linux"))]
90     Rds = libc::AF_RDS,
91     Sna = libc::AF_SNA,
92     #[cfg(any(target_os = "android", target_os = "linux"))]
93     Irda = libc::AF_IRDA,
94     #[cfg(any(target_os = "android", target_os = "linux"))]
95     Pppox = libc::AF_PPPOX,
96     #[cfg(any(target_os = "android", target_os = "linux"))]
97     Wanpipe = libc::AF_WANPIPE,
98     #[cfg(any(target_os = "android", target_os = "linux"))]
99     Llc = libc::AF_LLC,
100     #[cfg(target_os = "linux")]
101     Ib = libc::AF_IB,
102     #[cfg(target_os = "linux")]
103     Mpls = libc::AF_MPLS,
104     #[cfg(any(target_os = "android", target_os = "linux"))]
105     Can = libc::AF_CAN,
106     #[cfg(any(target_os = "android", target_os = "linux"))]
107     Tipc = libc::AF_TIPC,
108     #[cfg(not(any(target_os = "illumos",
109                   target_os = "ios",
110                   target_os = "macos",
111                   target_os = "solaris")))]
112     Bluetooth = libc::AF_BLUETOOTH,
113     #[cfg(any(target_os = "android", target_os = "linux"))]
114     Iucv = libc::AF_IUCV,
115     #[cfg(any(target_os = "android", target_os = "linux"))]
116     RxRpc = libc::AF_RXRPC,
117     #[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
118     Isdn = libc::AF_ISDN,
119     #[cfg(any(target_os = "android", target_os = "linux"))]
120     Phonet = libc::AF_PHONET,
121     #[cfg(any(target_os = "android", target_os = "linux"))]
122     Ieee802154 = libc::AF_IEEE802154,
123     #[cfg(any(target_os = "android", target_os = "linux"))]
124     Caif = libc::AF_CAIF,
125     /// Interface to kernel crypto API
126     #[cfg(any(target_os = "android", target_os = "linux"))]
127     Alg = libc::AF_ALG,
128     #[cfg(target_os = "linux")]
129     Nfc = libc::AF_NFC,
130     #[cfg(any(target_os = "android", target_os = "linux"))]
131     Vsock = libc::AF_VSOCK,
132     #[cfg(any(target_os = "dragonfly",
133               target_os = "freebsd",
134               target_os = "ios",
135               target_os = "macos",
136               target_os = "netbsd",
137               target_os = "openbsd"))]
138     ImpLink = libc::AF_IMPLINK,
139     #[cfg(any(target_os = "dragonfly",
140               target_os = "freebsd",
141               target_os = "ios",
142               target_os = "macos",
143               target_os = "netbsd",
144               target_os = "openbsd"))]
145     Pup = libc::AF_PUP,
146     #[cfg(any(target_os = "dragonfly",
147               target_os = "freebsd",
148               target_os = "ios",
149               target_os = "macos",
150               target_os = "netbsd",
151               target_os = "openbsd"))]
152     Chaos = libc::AF_CHAOS,
153     #[cfg(any(target_os = "ios",
154               target_os = "macos",
155               target_os = "netbsd",
156               target_os = "openbsd"))]
157     Ns = libc::AF_NS,
158     #[cfg(any(target_os = "dragonfly",
159               target_os = "freebsd",
160               target_os = "ios",
161               target_os = "macos",
162               target_os = "netbsd",
163               target_os = "openbsd"))]
164     Iso = libc::AF_ISO,
165     #[cfg(any(target_os = "dragonfly",
166               target_os = "freebsd",
167               target_os = "ios",
168               target_os = "macos",
169               target_os = "netbsd",
170               target_os = "openbsd"))]
171     Datakit = libc::AF_DATAKIT,
172     #[cfg(any(target_os = "dragonfly",
173               target_os = "freebsd",
174               target_os = "ios",
175               target_os = "macos",
176               target_os = "netbsd",
177               target_os = "openbsd"))]
178     Ccitt = libc::AF_CCITT,
179     #[cfg(any(target_os = "dragonfly",
180               target_os = "freebsd",
181               target_os = "ios",
182               target_os = "macos",
183               target_os = "netbsd",
184               target_os = "openbsd"))]
185     Dli = libc::AF_DLI,
186     #[cfg(any(target_os = "dragonfly",
187               target_os = "freebsd",
188               target_os = "ios",
189               target_os = "macos",
190               target_os = "netbsd",
191               target_os = "openbsd"))]
192     Lat = libc::AF_LAT,
193     #[cfg(any(target_os = "dragonfly",
194               target_os = "freebsd",
195               target_os = "ios",
196               target_os = "macos",
197               target_os = "netbsd",
198               target_os = "openbsd"))]
199     Hylink = libc::AF_HYLINK,
200     #[cfg(any(target_os = "dragonfly",
201               target_os = "freebsd",
202               target_os = "ios",
203               target_os = "macos",
204               target_os = "illumos",
205               target_os = "netbsd",
206               target_os = "openbsd"))]
207     Link = libc::AF_LINK,
208     #[cfg(any(target_os = "dragonfly",
209               target_os = "freebsd",
210               target_os = "ios",
211               target_os = "macos",
212               target_os = "netbsd",
213               target_os = "openbsd"))]
214     Coip = libc::AF_COIP,
215     #[cfg(any(target_os = "dragonfly",
216               target_os = "freebsd",
217               target_os = "ios",
218               target_os = "macos",
219               target_os = "netbsd",
220               target_os = "openbsd"))]
221     Cnt = libc::AF_CNT,
222     #[cfg(any(target_os = "dragonfly",
223               target_os = "freebsd",
224               target_os = "ios",
225               target_os = "macos",
226               target_os = "netbsd",
227               target_os = "openbsd"))]
228     Natm = libc::AF_NATM,
229     /// Unspecified address family, (see [`getaddrinfo(3)`](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html))
230     #[cfg(any(target_os = "android", target_os = "linux"))]
231     Unspec = libc::AF_UNSPEC,
232 }
233 
234 impl AddressFamily {
235     /// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from
236     /// the `sa_family` field of a `sockaddr`.
237     ///
238     /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet
239     /// and System. Returns None for unsupported or unknown address families.
from_i32(family: i32) -> Option<AddressFamily>240     pub const fn from_i32(family: i32) -> Option<AddressFamily> {
241         match family {
242             libc::AF_UNIX => Some(AddressFamily::Unix),
243             libc::AF_INET => Some(AddressFamily::Inet),
244             libc::AF_INET6 => Some(AddressFamily::Inet6),
245             #[cfg(any(target_os = "android", target_os = "linux"))]
246             libc::AF_NETLINK => Some(AddressFamily::Netlink),
247             #[cfg(any(target_os = "macos", target_os = "macos"))]
248             libc::AF_SYSTEM => Some(AddressFamily::System),
249             #[cfg(any(target_os = "android", target_os = "linux"))]
250             libc::AF_PACKET => Some(AddressFamily::Packet),
251             #[cfg(any(target_os = "dragonfly",
252                       target_os = "freebsd",
253                       target_os = "ios",
254                       target_os = "macos",
255                       target_os = "netbsd",
256                       target_os = "illumos",
257                       target_os = "openbsd"))]
258             libc::AF_LINK => Some(AddressFamily::Link),
259             #[cfg(any(target_os = "android", target_os = "linux"))]
260             libc::AF_VSOCK => Some(AddressFamily::Vsock),
261             _ => None
262         }
263     }
264 }
265 
266 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
267 pub enum InetAddr {
268     V4(libc::sockaddr_in),
269     V6(libc::sockaddr_in6),
270 }
271 
272 impl InetAddr {
273     #[allow(clippy::needless_update)]   // It isn't needless on all OSes
from_std(std: &net::SocketAddr) -> InetAddr274     pub fn from_std(std: &net::SocketAddr) -> InetAddr {
275         match *std {
276             net::SocketAddr::V4(ref addr) => {
277                 InetAddr::V4(libc::sockaddr_in {
278                     sin_family: AddressFamily::Inet as sa_family_t,
279                     sin_port: addr.port().to_be(),  // network byte order
280                     sin_addr: Ipv4Addr::from_std(addr.ip()).0,
281                     .. unsafe { mem::zeroed() }
282                 })
283             }
284             net::SocketAddr::V6(ref addr) => {
285                 InetAddr::V6(libc::sockaddr_in6 {
286                     sin6_family: AddressFamily::Inet6 as sa_family_t,
287                     sin6_port: addr.port().to_be(),  // network byte order
288                     sin6_addr: Ipv6Addr::from_std(addr.ip()).0,
289                     sin6_flowinfo: addr.flowinfo(),  // host byte order
290                     sin6_scope_id: addr.scope_id(),  // host byte order
291                     .. unsafe { mem::zeroed() }
292                 })
293             }
294         }
295     }
296 
297     #[allow(clippy::needless_update)]   // It isn't needless on all OSes
new(ip: IpAddr, port: u16) -> InetAddr298     pub fn new(ip: IpAddr, port: u16) -> InetAddr {
299         match ip {
300             IpAddr::V4(ref ip) => {
301                 InetAddr::V4(libc::sockaddr_in {
302                     sin_family: AddressFamily::Inet as sa_family_t,
303                     sin_port: port.to_be(),
304                     sin_addr: ip.0,
305                     .. unsafe { mem::zeroed() }
306                 })
307             }
308             IpAddr::V6(ref ip) => {
309                 InetAddr::V6(libc::sockaddr_in6 {
310                     sin6_family: AddressFamily::Inet6 as sa_family_t,
311                     sin6_port: port.to_be(),
312                     sin6_addr: ip.0,
313                     .. unsafe { mem::zeroed() }
314                 })
315             }
316         }
317     }
318     /// Gets the IP address associated with this socket address.
ip(&self) -> IpAddr319     pub const fn ip(&self) -> IpAddr {
320         match *self {
321             InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)),
322             InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)),
323         }
324     }
325 
326     /// Gets the port number associated with this socket address
port(&self) -> u16327     pub const fn port(&self) -> u16 {
328         match *self {
329             InetAddr::V6(ref sa) => u16::from_be(sa.sin6_port),
330             InetAddr::V4(ref sa) => u16::from_be(sa.sin_port),
331         }
332     }
333 
to_std(&self) -> net::SocketAddr334     pub fn to_std(&self) -> net::SocketAddr {
335         match *self {
336             InetAddr::V4(ref sa) => net::SocketAddr::V4(
337                 net::SocketAddrV4::new(
338                     Ipv4Addr(sa.sin_addr).to_std(),
339                     self.port())),
340             InetAddr::V6(ref sa) => net::SocketAddr::V6(
341                 net::SocketAddrV6::new(
342                     Ipv6Addr(sa.sin6_addr).to_std(),
343                     self.port(),
344                     sa.sin6_flowinfo,
345                     sa.sin6_scope_id)),
346         }
347     }
348 
349     #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
to_str(&self) -> String350     pub fn to_str(&self) -> String {
351         format!("{}", self)
352     }
353 }
354 
355 impl fmt::Display for InetAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result356     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
357         match *self {
358             InetAddr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()),
359             InetAddr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()),
360         }
361     }
362 }
363 
364 /*
365  *
366  * ===== IpAddr =====
367  *
368  */
369 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
370 pub enum IpAddr {
371     V4(Ipv4Addr),
372     V6(Ipv6Addr),
373 }
374 
375 impl IpAddr {
376     /// Create a new IpAddr that contains an IPv4 address.
377     ///
378     /// The result will represent the IP address a.b.c.d
new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr379     pub const fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr {
380         IpAddr::V4(Ipv4Addr::new(a, b, c, d))
381     }
382 
383     /// Create a new IpAddr that contains an IPv6 address.
384     ///
385     /// The result will represent the IP address a:b:c:d:e:f
386     #[allow(clippy::many_single_char_names)]
387     #[allow(clippy::too_many_arguments)]
new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr388     pub const fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
389         IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
390     }
391 
from_std(std: &net::IpAddr) -> IpAddr392     pub fn from_std(std: &net::IpAddr) -> IpAddr {
393         match *std {
394             net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)),
395             net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)),
396         }
397     }
398 
to_std(&self) -> net::IpAddr399     pub const fn to_std(&self) -> net::IpAddr {
400         match *self {
401             IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()),
402             IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()),
403         }
404     }
405 }
406 
407 impl fmt::Display for IpAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result408     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
409         match *self {
410             IpAddr::V4(ref v4) => v4.fmt(f),
411             IpAddr::V6(ref v6) => v6.fmt(f)
412         }
413     }
414 }
415 
416 /*
417  *
418  * ===== Ipv4Addr =====
419  *
420  */
421 
422 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
423 pub struct Ipv4Addr(pub libc::in_addr);
424 
425 impl Ipv4Addr {
426     #[allow(clippy::identity_op)]   // More readable this way
new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr427     pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
428         let ip = (((a as u32) << 24) |
429                   ((b as u32) << 16) |
430                   ((c as u32) <<  8) |
431                   ((d as u32) <<  0)).to_be();
432 
433         Ipv4Addr(libc::in_addr { s_addr: ip })
434     }
435 
436     // Use pass by reference for symmetry with Ipv6Addr::from_std
437     #[allow(clippy::trivially_copy_pass_by_ref)]
from_std(std: &net::Ipv4Addr) -> Ipv4Addr438     pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr {
439         let bits = std.octets();
440         Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
441     }
442 
any() -> Ipv4Addr443     pub const fn any() -> Ipv4Addr {
444         Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY })
445     }
446 
octets(self) -> [u8; 4]447     pub const fn octets(self) -> [u8; 4] {
448         let bits = u32::from_be(self.0.s_addr);
449         [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
450     }
451 
to_std(self) -> net::Ipv4Addr452     pub const fn to_std(self) -> net::Ipv4Addr {
453         let bits = self.octets();
454         net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
455     }
456 }
457 
458 impl fmt::Display for Ipv4Addr {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result459     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
460         let octets = self.octets();
461         write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
462     }
463 }
464 
465 /*
466  *
467  * ===== Ipv6Addr =====
468  *
469  */
470 
471 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
472 pub struct Ipv6Addr(pub libc::in6_addr);
473 
474 // Note that IPv6 addresses are stored in big endian order on all architectures.
475 // See https://tools.ietf.org/html/rfc1700 or consult your favorite search
476 // engine.
477 
478 macro_rules! to_u8_array {
479     ($($num:ident),*) => {
480         [ $(($num>>8) as u8, ($num&0xff) as u8,)* ]
481     }
482 }
483 
484 macro_rules! to_u16_array {
485     ($slf:ident, $($first:expr, $second:expr),*) => {
486         [$( (($slf.0.s6_addr[$first] as u16) << 8) + $slf.0.s6_addr[$second] as u16,)*]
487     }
488 }
489 
490 impl Ipv6Addr {
491     #[allow(clippy::many_single_char_names)]
492     #[allow(clippy::too_many_arguments)]
new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr493     pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
494         Ipv6Addr(libc::in6_addr{s6_addr: to_u8_array!(a,b,c,d,e,f,g,h)})
495     }
496 
from_std(std: &net::Ipv6Addr) -> Ipv6Addr497     pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr {
498         let s = std.segments();
499         Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
500     }
501 
502     /// Return the eight 16-bit segments that make up this address
segments(&self) -> [u16; 8]503     pub const fn segments(&self) -> [u16; 8] {
504         to_u16_array!(self, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
505     }
506 
to_std(&self) -> net::Ipv6Addr507     pub const fn to_std(&self) -> net::Ipv6Addr {
508         let s = self.segments();
509         net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
510     }
511 }
512 
513 impl fmt::Display for Ipv6Addr {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result514     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
515         self.to_std().fmt(fmt)
516     }
517 }
518 
519 /// A wrapper around `sockaddr_un`.
520 #[derive(Clone, Copy, Debug)]
521 pub struct UnixAddr {
522     // INVARIANT: sun & path_len are valid as defined by docs for from_raw_parts
523     sun: libc::sockaddr_un,
524     path_len: usize,
525 }
526 
527 // linux man page unix(7) says there are 3 kinds of unix socket:
528 // pathname: addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1
529 // unnamed: addrlen = sizeof(sa_family_t)
530 // abstract: addren > sizeof(sa_family_t), name = sun_path[..(addrlen - sizeof(sa_family_t))]
531 //
532 // what we call path_len = addrlen - offsetof(struct sockaddr_un, sun_path)
533 #[derive(PartialEq, Eq, Hash)]
534 enum UnixAddrKind<'a> {
535     Pathname(&'a Path),
536     Unnamed,
537     #[cfg(any(target_os = "android", target_os = "linux"))]
538     Abstract(&'a [u8]),
539 }
540 impl<'a> UnixAddrKind<'a> {
541     /// Safety: sun & path_len must be valid
get(sun: &'a libc::sockaddr_un, path_len: usize) -> Self542     unsafe fn get(sun: &'a libc::sockaddr_un, path_len: usize) -> Self {
543         if path_len == 0 {
544             return Self::Unnamed;
545         }
546         #[cfg(any(target_os = "android", target_os = "linux"))]
547         if sun.sun_path[0] == 0 {
548             let name =
549                 slice::from_raw_parts(sun.sun_path.as_ptr().add(1) as *const u8, path_len - 1);
550             return Self::Abstract(name);
551         }
552         let pathname = slice::from_raw_parts(sun.sun_path.as_ptr() as *const u8, path_len - 1);
553         Self::Pathname(Path::new(OsStr::from_bytes(pathname)))
554     }
555 }
556 
557 impl UnixAddr {
558     /// Create a new sockaddr_un representing a filesystem path.
new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr>559     pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
560         path.with_nix_path(|cstr| {
561             unsafe {
562                 let mut ret = libc::sockaddr_un {
563                     sun_family: AddressFamily::Unix as sa_family_t,
564                     .. mem::zeroed()
565                 };
566 
567                 let bytes = cstr.to_bytes();
568 
569                 if bytes.len() >= ret.sun_path.len() {
570                     return Err(Errno::ENAMETOOLONG);
571                 }
572 
573                 ptr::copy_nonoverlapping(bytes.as_ptr(),
574                                          ret.sun_path.as_mut_ptr() as *mut u8,
575                                          bytes.len());
576 
577                 Ok(UnixAddr::from_raw_parts(ret, bytes.len() + 1))
578             }
579         })?
580     }
581 
582     /// Create a new `sockaddr_un` representing an address in the "abstract namespace".
583     ///
584     /// The leading null byte for the abstract namespace is automatically added;
585     /// thus the input `path` is expected to be the bare name, not null-prefixed.
586     /// This is a Linux-specific extension, primarily used to allow chrooted
587     /// processes to communicate with processes having a different filesystem view.
588     #[cfg(any(target_os = "android", target_os = "linux"))]
new_abstract(path: &[u8]) -> Result<UnixAddr>589     pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
590         unsafe {
591             let mut ret = libc::sockaddr_un {
592                 sun_family: AddressFamily::Unix as sa_family_t,
593                 .. mem::zeroed()
594             };
595 
596             if path.len() >= ret.sun_path.len() {
597                 return Err(Errno::ENAMETOOLONG);
598             }
599 
600             // Abstract addresses are represented by sun_path[0] ==
601             // b'\0', so copy starting one byte in.
602             ptr::copy_nonoverlapping(path.as_ptr(),
603                                      ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
604                                      path.len());
605 
606             Ok(UnixAddr::from_raw_parts(ret, path.len() + 1))
607         }
608     }
609 
610     /// Create a UnixAddr from a raw `sockaddr_un` struct and a size. `path_len` is the "addrlen"
611     /// of this address, but minus `offsetof(struct sockaddr_un, sun_path)`. Basically the length
612     /// of the data in `sun_path`.
613     ///
614     /// # Safety
615     /// This pair of sockaddr_un & path_len must be a valid unix addr, which means:
616     /// - path_len <= sockaddr_un.sun_path.len()
617     /// - if this is a unix addr with a pathname, sun.sun_path is a nul-terminated fs path and
618     ///   sun.sun_path[path_len - 1] == 0 || sun.sun_path[path_len] == 0
from_raw_parts(sun: libc::sockaddr_un, mut path_len: usize) -> UnixAddr619     pub(crate) unsafe fn from_raw_parts(sun: libc::sockaddr_un, mut path_len: usize) -> UnixAddr {
620         if let UnixAddrKind::Pathname(_) = UnixAddrKind::get(&sun, path_len) {
621             if sun.sun_path[path_len - 1] != 0 {
622                 assert_eq!(sun.sun_path[path_len], 0);
623                 path_len += 1
624             }
625         }
626         UnixAddr { sun, path_len }
627     }
628 
kind(&self) -> UnixAddrKind<'_>629     fn kind(&self) -> UnixAddrKind<'_> {
630         // SAFETY: our sockaddr is always valid because of the invariant on the struct
631         unsafe { UnixAddrKind::get(&self.sun, self.path_len) }
632     }
633 
634     /// If this address represents a filesystem path, return that path.
path(&self) -> Option<&Path>635     pub fn path(&self) -> Option<&Path> {
636         match self.kind() {
637             UnixAddrKind::Pathname(path) => Some(path),
638             _ => None,
639         }
640     }
641 
642     /// If this address represents an abstract socket, return its name.
643     ///
644     /// For abstract sockets only the bare name is returned, without the
645     /// leading null byte. `None` is returned for unnamed or path-backed sockets.
646     #[cfg(any(target_os = "android", target_os = "linux"))]
as_abstract(&self) -> Option<&[u8]>647     pub fn as_abstract(&self) -> Option<&[u8]> {
648         match self.kind() {
649             UnixAddrKind::Abstract(name) => Some(name),
650             _ => None,
651         }
652     }
653 
654     /// Returns the addrlen of this socket - `offsetof(struct sockaddr_un, sun_path)`
655     #[inline]
path_len(&self) -> usize656     pub fn path_len(&self) -> usize {
657         self.path_len
658     }
659     /// Returns a pointer to the raw `sockaddr_un` struct
660     #[inline]
as_ptr(&self) -> *const libc::sockaddr_un661     pub fn as_ptr(&self) -> *const libc::sockaddr_un {
662         &self.sun
663     }
664     /// Returns a mutable pointer to the raw `sockaddr_un` struct
665     #[inline]
as_mut_ptr(&mut self) -> *mut libc::sockaddr_un666     pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr_un {
667         &mut self.sun
668     }
669 }
670 
671 #[cfg(any(target_os = "android", target_os = "linux"))]
fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result672 fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
673     use fmt::Write;
674     f.write_str("@\"")?;
675     for &b in abs {
676         use fmt::Display;
677         char::from(b).escape_default().fmt(f)?;
678     }
679     f.write_char('"')?;
680     Ok(())
681 }
682 
683 impl fmt::Display for UnixAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result684     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
685         match self.kind() {
686             UnixAddrKind::Pathname(path) => path.display().fmt(f),
687             UnixAddrKind::Unnamed => f.pad("<unbound UNIX socket>"),
688             #[cfg(any(target_os = "android", target_os = "linux"))]
689             UnixAddrKind::Abstract(name) => fmt_abstract(name, f),
690         }
691     }
692 }
693 
694 impl PartialEq for UnixAddr {
eq(&self, other: &UnixAddr) -> bool695     fn eq(&self, other: &UnixAddr) -> bool {
696         self.kind() == other.kind()
697     }
698 }
699 
700 impl Eq for UnixAddr {}
701 
702 impl Hash for UnixAddr {
hash<H: Hasher>(&self, s: &mut H)703     fn hash<H: Hasher>(&self, s: &mut H) {
704         self.kind().hash(s)
705     }
706 }
707 
708 /// Represents a socket address
709 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
710 #[non_exhaustive]
711 pub enum SockAddr {
712     Inet(InetAddr),
713     Unix(UnixAddr),
714     #[cfg(any(target_os = "android", target_os = "linux"))]
715     Netlink(NetlinkAddr),
716     #[cfg(any(target_os = "android", target_os = "linux"))]
717     Alg(AlgAddr),
718     #[cfg(any(target_os = "ios", target_os = "macos"))]
719     SysControl(SysControlAddr),
720     /// Datalink address (MAC)
721     #[cfg(any(target_os = "android",
722               target_os = "dragonfly",
723               target_os = "freebsd",
724               target_os = "ios",
725               target_os = "linux",
726               target_os = "macos",
727               target_os = "illumos",
728               target_os = "netbsd",
729               target_os = "openbsd"))]
730     Link(LinkAddr),
731     #[cfg(any(target_os = "android", target_os = "linux"))]
732     Vsock(VsockAddr),
733 }
734 
735 impl SockAddr {
new_inet(addr: InetAddr) -> SockAddr736     pub fn new_inet(addr: InetAddr) -> SockAddr {
737         SockAddr::Inet(addr)
738     }
739 
new_unix<P: ?Sized + NixPath>(path: &P) -> Result<SockAddr>740     pub fn new_unix<P: ?Sized + NixPath>(path: &P) -> Result<SockAddr> {
741         Ok(SockAddr::Unix(UnixAddr::new(path)?))
742     }
743 
744     #[cfg(any(target_os = "android", target_os = "linux"))]
new_netlink(pid: u32, groups: u32) -> SockAddr745     pub fn new_netlink(pid: u32, groups: u32) -> SockAddr {
746         SockAddr::Netlink(NetlinkAddr::new(pid, groups))
747     }
748 
749     #[cfg(any(target_os = "android", target_os = "linux"))]
new_alg(alg_type: &str, alg_name: &str) -> SockAddr750     pub fn new_alg(alg_type: &str, alg_name: &str) -> SockAddr {
751         SockAddr::Alg(AlgAddr::new(alg_type, alg_name))
752     }
753 
754     #[cfg(any(target_os = "ios", target_os = "macos"))]
new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr>755     pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> {
756         SysControlAddr::from_name(sockfd, name, unit).map(SockAddr::SysControl)
757     }
758 
759     #[cfg(any(target_os = "android", target_os = "linux"))]
new_vsock(cid: u32, port: u32) -> SockAddr760     pub fn new_vsock(cid: u32, port: u32) -> SockAddr {
761         SockAddr::Vsock(VsockAddr::new(cid, port))
762     }
763 
family(&self) -> AddressFamily764     pub fn family(&self) -> AddressFamily {
765         match *self {
766             SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
767             SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6,
768             SockAddr::Unix(..) => AddressFamily::Unix,
769             #[cfg(any(target_os = "android", target_os = "linux"))]
770             SockAddr::Netlink(..) => AddressFamily::Netlink,
771             #[cfg(any(target_os = "android", target_os = "linux"))]
772             SockAddr::Alg(..) => AddressFamily::Alg,
773             #[cfg(any(target_os = "ios", target_os = "macos"))]
774             SockAddr::SysControl(..) => AddressFamily::System,
775             #[cfg(any(target_os = "android", target_os = "linux"))]
776             SockAddr::Link(..) => AddressFamily::Packet,
777             #[cfg(any(target_os = "dragonfly",
778                       target_os = "freebsd",
779                       target_os = "ios",
780                       target_os = "macos",
781                       target_os = "netbsd",
782                       target_os = "illumos",
783                       target_os = "openbsd"))]
784             SockAddr::Link(..) => AddressFamily::Link,
785             #[cfg(any(target_os = "android", target_os = "linux"))]
786             SockAddr::Vsock(..) => AddressFamily::Vsock,
787         }
788     }
789 
790     #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
to_str(&self) -> String791     pub fn to_str(&self) -> String {
792         format!("{}", self)
793     }
794 
795     /// Creates a `SockAddr` struct from libc's sockaddr.
796     ///
797     /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System.
798     /// Returns None for unsupported families.
799     ///
800     /// # Safety
801     ///
802     /// unsafe because it takes a raw pointer as argument.  The caller must
803     /// ensure that the pointer is valid.
804     #[cfg(not(target_os = "fuchsia"))]
from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr>805     pub(crate) unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr> {
806         if addr.is_null() {
807             None
808         } else {
809             match AddressFamily::from_i32(i32::from((*addr).sa_family)) {
810                 Some(AddressFamily::Unix) => None,
811                 Some(AddressFamily::Inet) => Some(SockAddr::Inet(
812                     InetAddr::V4(*(addr as *const libc::sockaddr_in)))),
813                 Some(AddressFamily::Inet6) => Some(SockAddr::Inet(
814                     InetAddr::V6(*(addr as *const libc::sockaddr_in6)))),
815                 #[cfg(any(target_os = "android", target_os = "linux"))]
816                 Some(AddressFamily::Netlink) => Some(SockAddr::Netlink(
817                     NetlinkAddr(*(addr as *const libc::sockaddr_nl)))),
818                 #[cfg(any(target_os = "ios", target_os = "macos"))]
819                 Some(AddressFamily::System) => Some(SockAddr::SysControl(
820                     SysControlAddr(*(addr as *const libc::sockaddr_ctl)))),
821                 #[cfg(any(target_os = "android", target_os = "linux"))]
822                 Some(AddressFamily::Packet) => Some(SockAddr::Link(
823                     LinkAddr(*(addr as *const libc::sockaddr_ll)))),
824                 #[cfg(any(target_os = "dragonfly",
825                           target_os = "freebsd",
826                           target_os = "ios",
827                           target_os = "macos",
828                           target_os = "netbsd",
829                           target_os = "illumos",
830                           target_os = "openbsd"))]
831                 Some(AddressFamily::Link) => {
832                     let ether_addr = LinkAddr(*(addr as *const libc::sockaddr_dl));
833                     if ether_addr.is_empty() {
834                         None
835                     } else {
836                         Some(SockAddr::Link(ether_addr))
837                     }
838                 },
839                 #[cfg(any(target_os = "android", target_os = "linux"))]
840                 Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(
841                     VsockAddr(*(addr as *const libc::sockaddr_vm)))),
842                 // Other address families are currently not supported and simply yield a None
843                 // entry instead of a proper conversion to a `SockAddr`.
844                 Some(_) | None => None,
845             }
846         }
847     }
848 
849     /// Conversion from nix's SockAddr type to the underlying libc sockaddr type.
850     ///
851     /// This is useful for interfacing with other libc functions that don't yet have nix wrappers.
852     /// Returns a reference to the underlying data type (as a sockaddr reference) along
853     /// with the size of the actual data type. sockaddr is commonly used as a proxy for
854     /// a superclass as C doesn't support inheritance, so many functions that take
855     /// 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)856     pub fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
857         match *self {
858             SockAddr::Inet(InetAddr::V4(ref addr)) => (
859                 // This cast is always allowed in C
860                 unsafe {
861                     &*(addr as *const libc::sockaddr_in as *const libc::sockaddr)
862                 },
863                 mem::size_of_val(addr) as libc::socklen_t
864             ),
865             SockAddr::Inet(InetAddr::V6(ref addr)) => (
866                 // This cast is always allowed in C
867                 unsafe {
868                     &*(addr as *const libc::sockaddr_in6 as *const libc::sockaddr)
869                 },
870                 mem::size_of_val(addr) as libc::socklen_t
871             ),
872             SockAddr::Unix(UnixAddr { ref sun, path_len }) => (
873                 // This cast is always allowed in C
874                 unsafe {
875                     &*(sun as *const libc::sockaddr_un as *const libc::sockaddr)
876                 },
877                 (path_len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t
878             ),
879             #[cfg(any(target_os = "android", target_os = "linux"))]
880             SockAddr::Netlink(NetlinkAddr(ref sa)) => (
881                 // This cast is always allowed in C
882                 unsafe {
883                     &*(sa as *const libc::sockaddr_nl as *const libc::sockaddr)
884                 },
885                 mem::size_of_val(sa) as libc::socklen_t
886             ),
887             #[cfg(any(target_os = "android", target_os = "linux"))]
888             SockAddr::Alg(AlgAddr(ref sa)) => (
889                 // This cast is always allowed in C
890                 unsafe {
891                     &*(sa as *const libc::sockaddr_alg as *const libc::sockaddr)
892                 },
893                 mem::size_of_val(sa) as libc::socklen_t
894             ),
895             #[cfg(any(target_os = "ios", target_os = "macos"))]
896             SockAddr::SysControl(SysControlAddr(ref sa)) => (
897                 // This cast is always allowed in C
898                 unsafe {
899                     &*(sa as *const libc::sockaddr_ctl as *const libc::sockaddr)
900                 },
901                 mem::size_of_val(sa) as libc::socklen_t
902 
903             ),
904             #[cfg(any(target_os = "android", target_os = "linux"))]
905             SockAddr::Link(LinkAddr(ref addr)) => (
906                 // This cast is always allowed in C
907                 unsafe {
908                     &*(addr as *const libc::sockaddr_ll as *const libc::sockaddr)
909                 },
910                 mem::size_of_val(addr) as libc::socklen_t
911             ),
912             #[cfg(any(target_os = "dragonfly",
913                       target_os = "freebsd",
914                       target_os = "ios",
915                       target_os = "macos",
916                       target_os = "illumos",
917                       target_os = "netbsd",
918                       target_os = "openbsd"))]
919             SockAddr::Link(LinkAddr(ref addr)) => (
920                 // This cast is always allowed in C
921                 unsafe {
922                     &*(addr as *const libc::sockaddr_dl as *const libc::sockaddr)
923                 },
924                 mem::size_of_val(addr) as libc::socklen_t
925             ),
926             #[cfg(any(target_os = "android", target_os = "linux"))]
927             SockAddr::Vsock(VsockAddr(ref sa)) => (
928                 // This cast is always allowed in C
929                 unsafe {
930                     &*(sa as *const libc::sockaddr_vm as *const libc::sockaddr)
931                 },
932                 mem::size_of_val(sa) as libc::socklen_t
933             ),
934         }
935     }
936 }
937 
938 impl fmt::Display for SockAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result939     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
940         match *self {
941             SockAddr::Inet(ref inet) => inet.fmt(f),
942             SockAddr::Unix(ref unix) => unix.fmt(f),
943             #[cfg(any(target_os = "android", target_os = "linux"))]
944             SockAddr::Netlink(ref nl) => nl.fmt(f),
945             #[cfg(any(target_os = "android", target_os = "linux"))]
946             SockAddr::Alg(ref nl) => nl.fmt(f),
947             #[cfg(any(target_os = "ios", target_os = "macos"))]
948             SockAddr::SysControl(ref sc) => sc.fmt(f),
949             #[cfg(any(target_os = "android",
950                       target_os = "dragonfly",
951                       target_os = "freebsd",
952                       target_os = "ios",
953                       target_os = "linux",
954                       target_os = "macos",
955                       target_os = "netbsd",
956                       target_os = "illumos",
957                       target_os = "openbsd"))]
958             SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
959             #[cfg(any(target_os = "android", target_os = "linux"))]
960             SockAddr::Vsock(ref svm) => svm.fmt(f),
961         }
962     }
963 }
964 
965 #[cfg(any(target_os = "android", target_os = "linux"))]
966 pub mod netlink {
967     use crate::sys::socket::addr::AddressFamily;
968     use libc::{sa_family_t, sockaddr_nl};
969     use std::{fmt, mem};
970 
971     #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
972     pub struct NetlinkAddr(pub sockaddr_nl);
973 
974     impl NetlinkAddr {
new(pid: u32, groups: u32) -> NetlinkAddr975         pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
976             let mut addr: sockaddr_nl = unsafe { mem::zeroed() };
977             addr.nl_family = AddressFamily::Netlink as sa_family_t;
978             addr.nl_pid = pid;
979             addr.nl_groups = groups;
980 
981             NetlinkAddr(addr)
982         }
983 
pid(&self) -> u32984         pub const fn pid(&self) -> u32 {
985             self.0.nl_pid
986         }
987 
groups(&self) -> u32988         pub const fn groups(&self) -> u32 {
989             self.0.nl_groups
990         }
991     }
992 
993     impl fmt::Display for NetlinkAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result994         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
995             write!(f, "pid: {} groups: {}", self.pid(), self.groups())
996         }
997     }
998 }
999 
1000 #[cfg(any(target_os = "android", target_os = "linux"))]
1001 pub mod alg {
1002     use libc::{AF_ALG, sockaddr_alg, c_char};
1003     use std::{fmt, mem, str};
1004     use std::hash::{Hash, Hasher};
1005     use std::ffi::CStr;
1006 
1007     #[derive(Copy, Clone)]
1008     pub struct AlgAddr(pub sockaddr_alg);
1009 
1010     // , PartialEq, Eq, Debug, Hash
1011     impl PartialEq for AlgAddr {
eq(&self, other: &Self) -> bool1012         fn eq(&self, other: &Self) -> bool {
1013             let (inner, other) = (self.0, other.0);
1014             (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]) ==
1015             (other.salg_family, &other.salg_type[..], other.salg_feat, other.salg_mask, &other.salg_name[..])
1016         }
1017     }
1018 
1019     impl Eq for AlgAddr {}
1020 
1021     impl Hash for AlgAddr {
hash<H: Hasher>(&self, s: &mut H)1022         fn hash<H: Hasher>(&self, s: &mut H) {
1023             let inner = self.0;
1024             (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]).hash(s);
1025         }
1026     }
1027 
1028     impl AlgAddr {
new(alg_type: &str, alg_name: &str) -> AlgAddr1029         pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
1030             let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
1031             addr.salg_family = AF_ALG as u16;
1032             addr.salg_type[..alg_type.len()].copy_from_slice(alg_type.to_string().as_bytes());
1033             addr.salg_name[..alg_name.len()].copy_from_slice(alg_name.to_string().as_bytes());
1034 
1035             AlgAddr(addr)
1036         }
1037 
1038 
alg_type(&self) -> &CStr1039         pub fn alg_type(&self) -> &CStr {
1040             unsafe { CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char) }
1041         }
1042 
alg_name(&self) -> &CStr1043         pub fn alg_name(&self) -> &CStr {
1044             unsafe { CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char) }
1045         }
1046     }
1047 
1048     impl fmt::Display for AlgAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1049         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1050             write!(f, "type: {} alg: {}",
1051                    self.alg_name().to_string_lossy(),
1052                    self.alg_type().to_string_lossy())
1053         }
1054     }
1055 
1056     impl fmt::Debug for AlgAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1057         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1058             fmt::Display::fmt(self, f)
1059         }
1060     }
1061 }
1062 
1063 #[cfg(any(target_os = "ios", target_os = "macos"))]
1064 pub mod sys_control {
1065     use crate::sys::socket::addr::AddressFamily;
1066     use libc::{self, c_uchar};
1067     use std::{fmt, mem};
1068     use std::os::unix::io::RawFd;
1069     use crate::{Errno, Result};
1070 
1071     // FIXME: Move type into `libc`
1072     #[repr(C)]
1073     #[derive(Clone, Copy)]
1074     #[allow(missing_debug_implementations)]
1075     pub struct ctl_ioc_info {
1076         pub ctl_id: u32,
1077         pub ctl_name: [c_uchar; MAX_KCTL_NAME],
1078     }
1079 
1080     const CTL_IOC_MAGIC: u8 = b'N';
1081     const CTL_IOC_INFO: u8 = 3;
1082     const MAX_KCTL_NAME: usize = 96;
1083 
1084     ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info);
1085 
1086     #[repr(C)]
1087     #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1088     pub struct SysControlAddr(pub libc::sockaddr_ctl);
1089 
1090     impl SysControlAddr {
new(id: u32, unit: u32) -> SysControlAddr1091         pub const fn new(id: u32, unit: u32) -> SysControlAddr {
1092             let addr = libc::sockaddr_ctl {
1093                 sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
1094                 sc_family: AddressFamily::System as c_uchar,
1095                 ss_sysaddr: libc::AF_SYS_CONTROL as u16,
1096                 sc_id: id,
1097                 sc_unit: unit,
1098                 sc_reserved: [0; 5]
1099             };
1100 
1101             SysControlAddr(addr)
1102         }
1103 
from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr>1104         pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
1105             if name.len() > MAX_KCTL_NAME {
1106                 return Err(Errno::ENAMETOOLONG);
1107             }
1108 
1109             let mut ctl_name = [0; MAX_KCTL_NAME];
1110             ctl_name[..name.len()].clone_from_slice(name.as_bytes());
1111             let mut info = ctl_ioc_info { ctl_id: 0, ctl_name };
1112 
1113             unsafe { ctl_info(sockfd, &mut info)?; }
1114 
1115             Ok(SysControlAddr::new(info.ctl_id, unit))
1116         }
1117 
id(&self) -> u321118         pub const fn id(&self) -> u32 {
1119             self.0.sc_id
1120         }
1121 
unit(&self) -> u321122         pub const fn unit(&self) -> u32 {
1123             self.0.sc_unit
1124         }
1125     }
1126 
1127     impl fmt::Display for SysControlAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1128         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1129             fmt::Debug::fmt(self, f)
1130         }
1131     }
1132 }
1133 
1134 
1135 #[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
1136 mod datalink {
1137     use super::{fmt, AddressFamily};
1138 
1139     /// Hardware Address
1140     #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1141     pub struct LinkAddr(pub libc::sockaddr_ll);
1142 
1143     impl LinkAddr {
1144         /// Always AF_PACKET
family(&self) -> AddressFamily1145         pub fn family(&self) -> AddressFamily {
1146             assert_eq!(self.0.sll_family as i32, libc::AF_PACKET);
1147             AddressFamily::Packet
1148         }
1149 
1150         /// Physical-layer protocol
protocol(&self) -> u161151         pub fn protocol(&self) -> u16 {
1152             self.0.sll_protocol
1153         }
1154 
1155         /// Interface number
ifindex(&self) -> usize1156         pub fn ifindex(&self) -> usize {
1157             self.0.sll_ifindex as usize
1158         }
1159 
1160         /// ARP hardware type
hatype(&self) -> u161161         pub fn hatype(&self) -> u16 {
1162             self.0.sll_hatype
1163         }
1164 
1165         /// Packet type
pkttype(&self) -> u81166         pub fn pkttype(&self) -> u8 {
1167             self.0.sll_pkttype
1168         }
1169 
1170         /// Length of MAC address
halen(&self) -> usize1171         pub fn halen(&self) -> usize {
1172             self.0.sll_halen as usize
1173         }
1174 
1175         /// Physical-layer address (MAC)
addr(&self) -> [u8; 6]1176         pub fn addr(&self) -> [u8; 6] {
1177             [
1178                 self.0.sll_addr[0] as u8,
1179                 self.0.sll_addr[1] as u8,
1180                 self.0.sll_addr[2] as u8,
1181                 self.0.sll_addr[3] as u8,
1182                 self.0.sll_addr[4] as u8,
1183                 self.0.sll_addr[5] as u8,
1184             ]
1185         }
1186     }
1187 
1188     impl fmt::Display for LinkAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1189         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1190             let addr = self.addr();
1191             write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1192                 addr[0],
1193                 addr[1],
1194                 addr[2],
1195                 addr[3],
1196                 addr[4],
1197                 addr[5])
1198         }
1199     }
1200 }
1201 
1202 #[cfg(any(target_os = "dragonfly",
1203           target_os = "freebsd",
1204           target_os = "ios",
1205           target_os = "macos",
1206           target_os = "illumos",
1207           target_os = "netbsd",
1208           target_os = "openbsd"))]
1209 mod datalink {
1210     use super::{fmt, AddressFamily};
1211 
1212     /// Hardware Address
1213     #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1214     pub struct LinkAddr(pub libc::sockaddr_dl);
1215 
1216     impl LinkAddr {
1217         /// Total length of sockaddr
1218         #[cfg(not(target_os = "illumos"))]
len(&self) -> usize1219         pub fn len(&self) -> usize {
1220             self.0.sdl_len as usize
1221         }
1222 
1223         /// always == AF_LINK
family(&self) -> AddressFamily1224         pub fn family(&self) -> AddressFamily {
1225             assert_eq!(i32::from(self.0.sdl_family), libc::AF_LINK);
1226             AddressFamily::Link
1227         }
1228 
1229         /// interface index, if != 0, system given index for interface
ifindex(&self) -> usize1230         pub fn ifindex(&self) -> usize {
1231             self.0.sdl_index as usize
1232         }
1233 
1234         /// Datalink type
datalink_type(&self) -> u81235         pub fn datalink_type(&self) -> u8 {
1236             self.0.sdl_type
1237         }
1238 
1239         // MAC address start position
nlen(&self) -> usize1240         pub fn nlen(&self) -> usize {
1241             self.0.sdl_nlen as usize
1242         }
1243 
1244         /// link level address length
alen(&self) -> usize1245         pub fn alen(&self) -> usize {
1246             self.0.sdl_alen as usize
1247         }
1248 
1249         /// link layer selector length
slen(&self) -> usize1250         pub fn slen(&self) -> usize {
1251             self.0.sdl_slen as usize
1252         }
1253 
1254         /// if link level address length == 0,
1255         /// or `sdl_data` not be larger.
is_empty(&self) -> bool1256         pub fn is_empty(&self) -> bool {
1257             let nlen = self.nlen();
1258             let alen = self.alen();
1259             let data_len = self.0.sdl_data.len();
1260 
1261             alen == 0 || nlen + alen >= data_len
1262         }
1263 
1264         /// Physical-layer address (MAC)
addr(&self) -> [u8; 6]1265         pub fn addr(&self) -> [u8; 6] {
1266             let nlen = self.nlen();
1267             let data = self.0.sdl_data;
1268 
1269             assert!(!self.is_empty());
1270 
1271             [
1272                 data[nlen] as u8,
1273                 data[nlen + 1] as u8,
1274                 data[nlen + 2] as u8,
1275                 data[nlen + 3] as u8,
1276                 data[nlen + 4] as u8,
1277                 data[nlen + 5] as u8,
1278             ]
1279         }
1280     }
1281 
1282     impl fmt::Display for LinkAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1283         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1284             let addr = self.addr();
1285             write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1286                 addr[0],
1287                 addr[1],
1288                 addr[2],
1289                 addr[3],
1290                 addr[4],
1291                 addr[5])
1292         }
1293     }
1294 }
1295 
1296 #[cfg(any(target_os = "android", target_os = "linux"))]
1297 pub mod vsock {
1298     use crate::sys::socket::addr::AddressFamily;
1299     use libc::{sa_family_t, sockaddr_vm};
1300     use std::{fmt, mem};
1301     use std::hash::{Hash, Hasher};
1302 
1303     #[derive(Copy, Clone)]
1304     pub struct VsockAddr(pub sockaddr_vm);
1305 
1306     impl PartialEq for VsockAddr {
eq(&self, other: &Self) -> bool1307         fn eq(&self, other: &Self) -> bool {
1308             let (inner, other) = (self.0, other.0);
1309             (inner.svm_family, inner.svm_cid, inner.svm_port) ==
1310             (other.svm_family, other.svm_cid, other.svm_port)
1311         }
1312     }
1313 
1314     impl Eq for VsockAddr {}
1315 
1316     impl Hash for VsockAddr {
hash<H: Hasher>(&self, s: &mut H)1317         fn hash<H: Hasher>(&self, s: &mut H) {
1318             let inner = self.0;
1319             (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
1320         }
1321     }
1322 
1323     /// VSOCK Address
1324     ///
1325     /// The address for AF_VSOCK socket is defined as a combination of a
1326     /// 32-bit Context Identifier (CID) and a 32-bit port number.
1327     impl VsockAddr {
new(cid: u32, port: u32) -> VsockAddr1328         pub fn new(cid: u32, port: u32) -> VsockAddr {
1329             let mut addr: sockaddr_vm = unsafe { mem::zeroed() };
1330             addr.svm_family = AddressFamily::Vsock as sa_family_t;
1331             addr.svm_cid = cid;
1332             addr.svm_port = port;
1333 
1334             VsockAddr(addr)
1335         }
1336 
1337         /// Context Identifier (CID)
cid(&self) -> u321338         pub fn cid(&self) -> u32 {
1339             self.0.svm_cid
1340         }
1341 
1342         /// Port number
port(&self) -> u321343         pub fn port(&self) -> u32 {
1344             self.0.svm_port
1345         }
1346     }
1347 
1348     impl fmt::Display for VsockAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1349         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1350             write!(f, "cid: {} port: {}", self.cid(), self.port())
1351         }
1352     }
1353 
1354     impl fmt::Debug for VsockAddr {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1355         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1356             fmt::Display::fmt(self, f)
1357         }
1358     }
1359 }
1360 
1361 #[cfg(test)]
1362 mod tests {
1363     #[cfg(any(target_os = "android",
1364               target_os = "dragonfly",
1365               target_os = "freebsd",
1366               target_os = "ios",
1367               target_os = "linux",
1368               target_os = "macos",
1369               target_os = "netbsd",
1370               target_os = "illumos",
1371               target_os = "openbsd"))]
1372     use super::*;
1373 
1374     #[cfg(any(target_os = "dragonfly",
1375               target_os = "freebsd",
1376               target_os = "ios",
1377               target_os = "macos",
1378               target_os = "netbsd",
1379               target_os = "openbsd"))]
1380     #[test]
test_macos_loopback_datalink_addr()1381     fn test_macos_loopback_datalink_addr() {
1382         let bytes = [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
1383         let sa = bytes.as_ptr() as *const libc::sockaddr;
1384         let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
1385         assert!(_sock_addr.is_none());
1386     }
1387 
1388     #[cfg(any(target_os = "dragonfly",
1389               target_os = "freebsd",
1390               target_os = "ios",
1391               target_os = "macos",
1392               target_os = "netbsd",
1393               target_os = "openbsd"))]
1394     #[test]
test_macos_tap_datalink_addr()1395     fn test_macos_tap_datalink_addr() {
1396         let bytes = [20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35, 76, -80];
1397         let ptr = bytes.as_ptr();
1398         let sa = ptr as *const libc::sockaddr;
1399         let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
1400 
1401         assert!(_sock_addr.is_some());
1402 
1403         let sock_addr = _sock_addr.unwrap();
1404 
1405         assert_eq!(sock_addr.family(), AddressFamily::Link);
1406 
1407         match sock_addr {
1408             SockAddr::Link(ether_addr) => {
1409                 assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]);
1410             },
1411             _ => { unreachable!() }
1412         };
1413     }
1414 
1415     #[cfg(target_os = "illumos")]
1416     #[test]
test_illumos_tap_datalink_addr()1417     fn test_illumos_tap_datalink_addr() {
1418         let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176];
1419         let ptr = bytes.as_ptr();
1420         let sa = ptr as *const libc::sockaddr;
1421         let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
1422 
1423         assert!(_sock_addr.is_some());
1424 
1425         let sock_addr = _sock_addr.unwrap();
1426 
1427         assert_eq!(sock_addr.family(), AddressFamily::Link);
1428 
1429         match sock_addr {
1430             SockAddr::Link(ether_addr) => {
1431                 assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]);
1432             },
1433             _ => { unreachable!() }
1434         };
1435     }
1436 
1437     #[cfg(any(target_os = "android", target_os = "linux"))]
1438     #[test]
test_abstract_sun_path()1439     fn test_abstract_sun_path() {
1440         let name = String::from("nix\0abstract\0test");
1441         let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
1442 
1443         let sun_path1 = unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] };
1444         let sun_path2 = [0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116];
1445         assert_eq!(sun_path1, sun_path2);
1446     }
1447 }
1448