nix/sys/socket/
addr.rs

1use super::sa_family_t;
2use crate::{Result, NixPath};
3use crate::errno::Errno;
4use memoffset::offset_of;
5use std::{fmt, mem, net, ptr, slice};
6use std::ffi::OsStr;
7use std::hash::{Hash, Hasher};
8use std::path::Path;
9use std::os::unix::ffi::OsStrExt;
10#[cfg(any(target_os = "android", target_os = "linux"))]
11use crate::sys::socket::addr::netlink::NetlinkAddr;
12#[cfg(any(target_os = "android", target_os = "linux"))]
13use crate::sys::socket::addr::alg::AlgAddr;
14#[cfg(any(target_os = "ios", target_os = "macos"))]
15use std::os::unix::io::RawFd;
16#[cfg(any(target_os = "ios", target_os = "macos"))]
17use 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"))]
28pub use self::datalink::LinkAddr;
29#[cfg(any(target_os = "android", target_os = "linux"))]
30pub 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)]
37pub 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
234impl 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.
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)]
267pub enum InetAddr {
268    V4(libc::sockaddr_in),
269    V6(libc::sockaddr_in6),
270}
271
272impl InetAddr {
273    #[allow(clippy::needless_update)]   // It isn't needless on all OSes
274    pub fn from_std(std: &net::SocketAddr) -> InetAddr {
275        match *std {
276            net::SocketAddr::V4(ref addr) => {
277                InetAddr::V4(libc::sockaddr_in {
278                    #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
279                              target_os = "haiku", target_os = "hermit",
280                              target_os = "ios", target_os = "macos",
281                              target_os = "netbsd", target_os = "openbsd"))]
282                    sin_len: mem::size_of::<libc::sockaddr_in>() as u8,
283                    sin_family: AddressFamily::Inet as sa_family_t,
284                    sin_port: addr.port().to_be(),  // network byte order
285                    sin_addr: Ipv4Addr::from_std(addr.ip()).0,
286                    .. unsafe { mem::zeroed() }
287                })
288            }
289            net::SocketAddr::V6(ref addr) => {
290                InetAddr::V6(libc::sockaddr_in6 {
291                    #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
292                              target_os = "haiku", target_os = "hermit",
293                              target_os = "ios", target_os = "macos",
294                              target_os = "netbsd", target_os = "openbsd"))]
295                    sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8,
296                    sin6_family: AddressFamily::Inet6 as sa_family_t,
297                    sin6_port: addr.port().to_be(),  // network byte order
298                    sin6_addr: Ipv6Addr::from_std(addr.ip()).0,
299                    sin6_flowinfo: addr.flowinfo(),  // host byte order
300                    sin6_scope_id: addr.scope_id(),  // host byte order
301                    .. unsafe { mem::zeroed() }
302                })
303            }
304        }
305    }
306
307    #[allow(clippy::needless_update)]   // It isn't needless on all OSes
308    pub fn new(ip: IpAddr, port: u16) -> InetAddr {
309        match ip {
310            IpAddr::V4(ref ip) => {
311                InetAddr::V4(libc::sockaddr_in {
312                    sin_family: AddressFamily::Inet as sa_family_t,
313                    sin_port: port.to_be(),
314                    sin_addr: ip.0,
315                    .. unsafe { mem::zeroed() }
316                })
317            }
318            IpAddr::V6(ref ip) => {
319                InetAddr::V6(libc::sockaddr_in6 {
320                    sin6_family: AddressFamily::Inet6 as sa_family_t,
321                    sin6_port: port.to_be(),
322                    sin6_addr: ip.0,
323                    .. unsafe { mem::zeroed() }
324                })
325            }
326        }
327    }
328    /// Gets the IP address associated with this socket address.
329    pub const fn ip(&self) -> IpAddr {
330        match *self {
331            InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)),
332            InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)),
333        }
334    }
335
336    /// Gets the port number associated with this socket address
337    pub const fn port(&self) -> u16 {
338        match *self {
339            InetAddr::V6(ref sa) => u16::from_be(sa.sin6_port),
340            InetAddr::V4(ref sa) => u16::from_be(sa.sin_port),
341        }
342    }
343
344    pub fn to_std(&self) -> net::SocketAddr {
345        match *self {
346            InetAddr::V4(ref sa) => net::SocketAddr::V4(
347                net::SocketAddrV4::new(
348                    Ipv4Addr(sa.sin_addr).to_std(),
349                    self.port())),
350            InetAddr::V6(ref sa) => net::SocketAddr::V6(
351                net::SocketAddrV6::new(
352                    Ipv6Addr(sa.sin6_addr).to_std(),
353                    self.port(),
354                    sa.sin6_flowinfo,
355                    sa.sin6_scope_id)),
356        }
357    }
358
359    #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
360    pub fn to_str(&self) -> String {
361        format!("{}", self)
362    }
363}
364
365impl fmt::Display for InetAddr {
366    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
367        match *self {
368            InetAddr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()),
369            InetAddr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()),
370        }
371    }
372}
373
374/*
375 *
376 * ===== IpAddr =====
377 *
378 */
379#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
380pub enum IpAddr {
381    V4(Ipv4Addr),
382    V6(Ipv6Addr),
383}
384
385impl IpAddr {
386    /// Create a new IpAddr that contains an IPv4 address.
387    ///
388    /// The result will represent the IP address a.b.c.d
389    pub const fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr {
390        IpAddr::V4(Ipv4Addr::new(a, b, c, d))
391    }
392
393    /// Create a new IpAddr that contains an IPv6 address.
394    ///
395    /// The result will represent the IP address a:b:c:d:e:f
396    #[allow(clippy::many_single_char_names)]
397    #[allow(clippy::too_many_arguments)]
398    pub const fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
399        IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
400    }
401
402    pub fn from_std(std: &net::IpAddr) -> IpAddr {
403        match *std {
404            net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)),
405            net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)),
406        }
407    }
408
409    pub const fn to_std(&self) -> net::IpAddr {
410        match *self {
411            IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()),
412            IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()),
413        }
414    }
415}
416
417impl fmt::Display for IpAddr {
418    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
419        match *self {
420            IpAddr::V4(ref v4) => v4.fmt(f),
421            IpAddr::V6(ref v6) => v6.fmt(f)
422        }
423    }
424}
425
426/*
427 *
428 * ===== Ipv4Addr =====
429 *
430 */
431
432#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
433pub struct Ipv4Addr(pub libc::in_addr);
434
435impl Ipv4Addr {
436    #[allow(clippy::identity_op)]   // More readable this way
437    pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
438        let ip = (((a as u32) << 24) |
439                  ((b as u32) << 16) |
440                  ((c as u32) <<  8) |
441                  ((d as u32) <<  0)).to_be();
442
443        Ipv4Addr(libc::in_addr { s_addr: ip })
444    }
445
446    // Use pass by reference for symmetry with Ipv6Addr::from_std
447    #[allow(clippy::trivially_copy_pass_by_ref)]
448    pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr {
449        let bits = std.octets();
450        Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
451    }
452
453    pub const fn any() -> Ipv4Addr {
454        Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY })
455    }
456
457    pub const fn octets(self) -> [u8; 4] {
458        let bits = u32::from_be(self.0.s_addr);
459        [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
460    }
461
462    pub const fn to_std(self) -> net::Ipv4Addr {
463        let bits = self.octets();
464        net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
465    }
466}
467
468impl fmt::Display for Ipv4Addr {
469    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
470        let octets = self.octets();
471        write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
472    }
473}
474
475/*
476 *
477 * ===== Ipv6Addr =====
478 *
479 */
480
481#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
482pub struct Ipv6Addr(pub libc::in6_addr);
483
484// Note that IPv6 addresses are stored in big endian order on all architectures.
485// See https://tools.ietf.org/html/rfc1700 or consult your favorite search
486// engine.
487
488macro_rules! to_u8_array {
489    ($($num:ident),*) => {
490        [ $(($num>>8) as u8, ($num&0xff) as u8,)* ]
491    }
492}
493
494macro_rules! to_u16_array {
495    ($slf:ident, $($first:expr, $second:expr),*) => {
496        [$( (($slf.0.s6_addr[$first] as u16) << 8) + $slf.0.s6_addr[$second] as u16,)*]
497    }
498}
499
500impl Ipv6Addr {
501    #[allow(clippy::many_single_char_names)]
502    #[allow(clippy::too_many_arguments)]
503    pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
504        Ipv6Addr(libc::in6_addr{s6_addr: to_u8_array!(a,b,c,d,e,f,g,h)})
505    }
506
507    pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr {
508        let s = std.segments();
509        Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
510    }
511
512    /// Return the eight 16-bit segments that make up this address
513    pub const fn segments(&self) -> [u16; 8] {
514        to_u16_array!(self, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
515    }
516
517    pub const fn to_std(&self) -> net::Ipv6Addr {
518        let s = self.segments();
519        net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
520    }
521}
522
523impl fmt::Display for Ipv6Addr {
524    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
525        self.to_std().fmt(fmt)
526    }
527}
528
529/// A wrapper around `sockaddr_un`.
530#[derive(Clone, Copy, Debug)]
531pub struct UnixAddr {
532    // INVARIANT: sun & path_len are valid as defined by docs for from_raw_parts
533    sun: libc::sockaddr_un,
534    path_len: usize,
535}
536
537// linux man page unix(7) says there are 3 kinds of unix socket:
538// pathname: addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1
539// unnamed: addrlen = sizeof(sa_family_t)
540// abstract: addren > sizeof(sa_family_t), name = sun_path[..(addrlen - sizeof(sa_family_t))]
541//
542// what we call path_len = addrlen - offsetof(struct sockaddr_un, sun_path)
543#[derive(PartialEq, Eq, Hash)]
544enum UnixAddrKind<'a> {
545    Pathname(&'a Path),
546    Unnamed,
547    #[cfg(any(target_os = "android", target_os = "linux"))]
548    Abstract(&'a [u8]),
549}
550impl<'a> UnixAddrKind<'a> {
551    /// Safety: sun & path_len must be valid
552    unsafe fn get(sun: &'a libc::sockaddr_un, path_len: usize) -> Self {
553        if path_len == 0 {
554            return Self::Unnamed;
555        }
556        #[cfg(any(target_os = "android", target_os = "linux"))]
557        if sun.sun_path[0] == 0 {
558            let name =
559                slice::from_raw_parts(sun.sun_path.as_ptr().add(1) as *const u8, path_len - 1);
560            return Self::Abstract(name);
561        }
562        let pathname = slice::from_raw_parts(sun.sun_path.as_ptr() as *const u8, path_len - 1);
563        Self::Pathname(Path::new(OsStr::from_bytes(pathname)))
564    }
565}
566
567impl UnixAddr {
568    /// Create a new sockaddr_un representing a filesystem path.
569    pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
570        path.with_nix_path(|cstr| {
571            unsafe {
572                let mut ret = libc::sockaddr_un {
573                    sun_family: AddressFamily::Unix as sa_family_t,
574                    .. mem::zeroed()
575                };
576
577                let bytes = cstr.to_bytes();
578
579                if bytes.len() >= ret.sun_path.len() {
580                    return Err(Errno::ENAMETOOLONG);
581                }
582
583                ptr::copy_nonoverlapping(bytes.as_ptr(),
584                                         ret.sun_path.as_mut_ptr() as *mut u8,
585                                         bytes.len());
586
587                Ok(UnixAddr::from_raw_parts(ret, bytes.len() + 1))
588            }
589        })?
590    }
591
592    /// Create a new `sockaddr_un` representing an address in the "abstract namespace".
593    ///
594    /// The leading null byte for the abstract namespace is automatically added;
595    /// thus the input `path` is expected to be the bare name, not null-prefixed.
596    /// This is a Linux-specific extension, primarily used to allow chrooted
597    /// processes to communicate with processes having a different filesystem view.
598    #[cfg(any(target_os = "android", target_os = "linux"))]
599    pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
600        unsafe {
601            let mut ret = libc::sockaddr_un {
602                sun_family: AddressFamily::Unix as sa_family_t,
603                .. mem::zeroed()
604            };
605
606            if path.len() >= ret.sun_path.len() {
607                return Err(Errno::ENAMETOOLONG);
608            }
609
610            // Abstract addresses are represented by sun_path[0] ==
611            // b'\0', so copy starting one byte in.
612            ptr::copy_nonoverlapping(path.as_ptr(),
613                                     ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
614                                     path.len());
615
616            Ok(UnixAddr::from_raw_parts(ret, path.len() + 1))
617        }
618    }
619
620    /// Create a UnixAddr from a raw `sockaddr_un` struct and a size. `path_len` is the "addrlen"
621    /// of this address, but minus `offsetof(struct sockaddr_un, sun_path)`. Basically the length
622    /// of the data in `sun_path`.
623    ///
624    /// # Safety
625    /// This pair of sockaddr_un & path_len must be a valid unix addr, which means:
626    /// - path_len <= sockaddr_un.sun_path.len()
627    /// - if this is a unix addr with a pathname, sun.sun_path is a nul-terminated fs path and
628    ///   sun.sun_path[path_len - 1] == 0 || sun.sun_path[path_len] == 0
629    pub(crate) unsafe fn from_raw_parts(sun: libc::sockaddr_un, mut path_len: usize) -> UnixAddr {
630        if let UnixAddrKind::Pathname(_) = UnixAddrKind::get(&sun, path_len) {
631            if sun.sun_path[path_len - 1] != 0 {
632                assert_eq!(sun.sun_path[path_len], 0);
633                path_len += 1
634            }
635        }
636        UnixAddr { sun, path_len }
637    }
638
639    fn kind(&self) -> UnixAddrKind<'_> {
640        // SAFETY: our sockaddr is always valid because of the invariant on the struct
641        unsafe { UnixAddrKind::get(&self.sun, self.path_len) }
642    }
643
644    /// If this address represents a filesystem path, return that path.
645    pub fn path(&self) -> Option<&Path> {
646        match self.kind() {
647            UnixAddrKind::Pathname(path) => Some(path),
648            _ => None,
649        }
650    }
651
652    /// If this address represents an abstract socket, return its name.
653    ///
654    /// For abstract sockets only the bare name is returned, without the
655    /// leading null byte. `None` is returned for unnamed or path-backed sockets.
656    #[cfg(any(target_os = "android", target_os = "linux"))]
657    pub fn as_abstract(&self) -> Option<&[u8]> {
658        match self.kind() {
659            UnixAddrKind::Abstract(name) => Some(name),
660            _ => None,
661        }
662    }
663
664    /// Returns the addrlen of this socket - `offsetof(struct sockaddr_un, sun_path)`
665    #[inline]
666    pub fn path_len(&self) -> usize {
667        self.path_len
668    }
669    /// Returns a pointer to the raw `sockaddr_un` struct
670    #[inline]
671    pub fn as_ptr(&self) -> *const libc::sockaddr_un {
672        &self.sun
673    }
674    /// Returns a mutable pointer to the raw `sockaddr_un` struct
675    #[inline]
676    pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr_un {
677        &mut self.sun
678    }
679}
680
681#[cfg(any(target_os = "android", target_os = "linux"))]
682fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
683    use fmt::Write;
684    f.write_str("@\"")?;
685    for &b in abs {
686        use fmt::Display;
687        char::from(b).escape_default().fmt(f)?;
688    }
689    f.write_char('"')?;
690    Ok(())
691}
692
693impl fmt::Display for UnixAddr {
694    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
695        match self.kind() {
696            UnixAddrKind::Pathname(path) => path.display().fmt(f),
697            UnixAddrKind::Unnamed => f.pad("<unbound UNIX socket>"),
698            #[cfg(any(target_os = "android", target_os = "linux"))]
699            UnixAddrKind::Abstract(name) => fmt_abstract(name, f),
700        }
701    }
702}
703
704impl PartialEq for UnixAddr {
705    fn eq(&self, other: &UnixAddr) -> bool {
706        self.kind() == other.kind()
707    }
708}
709
710impl Eq for UnixAddr {}
711
712impl Hash for UnixAddr {
713    fn hash<H: Hasher>(&self, s: &mut H) {
714        self.kind().hash(s)
715    }
716}
717
718/// Represents a socket address
719#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
720#[non_exhaustive]
721pub enum SockAddr {
722    Inet(InetAddr),
723    Unix(UnixAddr),
724    #[cfg(any(target_os = "android", target_os = "linux"))]
725    Netlink(NetlinkAddr),
726    #[cfg(any(target_os = "android", target_os = "linux"))]
727    Alg(AlgAddr),
728    #[cfg(any(target_os = "ios", target_os = "macos"))]
729    SysControl(SysControlAddr),
730    /// Datalink address (MAC)
731    #[cfg(any(target_os = "android",
732              target_os = "dragonfly",
733              target_os = "freebsd",
734              target_os = "ios",
735              target_os = "linux",
736              target_os = "macos",
737              target_os = "illumos",
738              target_os = "netbsd",
739              target_os = "openbsd"))]
740    Link(LinkAddr),
741    #[cfg(any(target_os = "android", target_os = "linux"))]
742    Vsock(VsockAddr),
743}
744
745impl SockAddr {
746    pub fn new_inet(addr: InetAddr) -> SockAddr {
747        SockAddr::Inet(addr)
748    }
749
750    pub fn new_unix<P: ?Sized + NixPath>(path: &P) -> Result<SockAddr> {
751        Ok(SockAddr::Unix(UnixAddr::new(path)?))
752    }
753
754    #[cfg(any(target_os = "android", target_os = "linux"))]
755    pub fn new_netlink(pid: u32, groups: u32) -> SockAddr {
756        SockAddr::Netlink(NetlinkAddr::new(pid, groups))
757    }
758
759    #[cfg(any(target_os = "android", target_os = "linux"))]
760    pub fn new_alg(alg_type: &str, alg_name: &str) -> SockAddr {
761        SockAddr::Alg(AlgAddr::new(alg_type, alg_name))
762    }
763
764    #[cfg(any(target_os = "ios", target_os = "macos"))]
765    pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> {
766        SysControlAddr::from_name(sockfd, name, unit).map(SockAddr::SysControl)
767    }
768
769    #[cfg(any(target_os = "android", target_os = "linux"))]
770    pub fn new_vsock(cid: u32, port: u32) -> SockAddr {
771        SockAddr::Vsock(VsockAddr::new(cid, port))
772    }
773
774    pub fn family(&self) -> AddressFamily {
775        match *self {
776            SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
777            SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6,
778            SockAddr::Unix(..) => AddressFamily::Unix,
779            #[cfg(any(target_os = "android", target_os = "linux"))]
780            SockAddr::Netlink(..) => AddressFamily::Netlink,
781            #[cfg(any(target_os = "android", target_os = "linux"))]
782            SockAddr::Alg(..) => AddressFamily::Alg,
783            #[cfg(any(target_os = "ios", target_os = "macos"))]
784            SockAddr::SysControl(..) => AddressFamily::System,
785            #[cfg(any(target_os = "android", target_os = "linux"))]
786            SockAddr::Link(..) => AddressFamily::Packet,
787            #[cfg(any(target_os = "dragonfly",
788                      target_os = "freebsd",
789                      target_os = "ios",
790                      target_os = "macos",
791                      target_os = "netbsd",
792                      target_os = "illumos",
793                      target_os = "openbsd"))]
794            SockAddr::Link(..) => AddressFamily::Link,
795            #[cfg(any(target_os = "android", target_os = "linux"))]
796            SockAddr::Vsock(..) => AddressFamily::Vsock,
797        }
798    }
799
800    #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
801    pub fn to_str(&self) -> String {
802        format!("{}", self)
803    }
804
805    /// Creates a `SockAddr` struct from libc's sockaddr.
806    ///
807    /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System.
808    /// Returns None for unsupported families.
809    ///
810    /// # Safety
811    ///
812    /// unsafe because it takes a raw pointer as argument.  The caller must
813    /// ensure that the pointer is valid.
814    #[cfg(not(target_os = "fuchsia"))]
815    pub(crate) unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr> {
816        if addr.is_null() {
817            None
818        } else {
819            match AddressFamily::from_i32(i32::from((*addr).sa_family)) {
820                Some(AddressFamily::Unix) => None,
821                Some(AddressFamily::Inet) => Some(SockAddr::Inet(
822                    InetAddr::V4(*(addr as *const libc::sockaddr_in)))),
823                Some(AddressFamily::Inet6) => Some(SockAddr::Inet(
824                    InetAddr::V6(*(addr as *const libc::sockaddr_in6)))),
825                #[cfg(any(target_os = "android", target_os = "linux"))]
826                Some(AddressFamily::Netlink) => Some(SockAddr::Netlink(
827                    NetlinkAddr(*(addr as *const libc::sockaddr_nl)))),
828                #[cfg(any(target_os = "ios", target_os = "macos"))]
829                Some(AddressFamily::System) => Some(SockAddr::SysControl(
830                    SysControlAddr(*(addr as *const libc::sockaddr_ctl)))),
831                #[cfg(any(target_os = "android", target_os = "linux"))]
832                Some(AddressFamily::Packet) => Some(SockAddr::Link(
833                    LinkAddr(*(addr as *const libc::sockaddr_ll)))),
834                #[cfg(any(target_os = "dragonfly",
835                          target_os = "freebsd",
836                          target_os = "ios",
837                          target_os = "macos",
838                          target_os = "netbsd",
839                          target_os = "illumos",
840                          target_os = "openbsd"))]
841                Some(AddressFamily::Link) => {
842                    let ether_addr = LinkAddr(*(addr as *const libc::sockaddr_dl));
843                    if ether_addr.is_empty() {
844                        None
845                    } else {
846                        Some(SockAddr::Link(ether_addr))
847                    }
848                },
849                #[cfg(any(target_os = "android", target_os = "linux"))]
850                Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(
851                    VsockAddr(*(addr as *const libc::sockaddr_vm)))),
852                // Other address families are currently not supported and simply yield a None
853                // entry instead of a proper conversion to a `SockAddr`.
854                Some(_) | None => None,
855            }
856        }
857    }
858
859    /// Conversion from nix's SockAddr type to the underlying libc sockaddr type.
860    ///
861    /// This is useful for interfacing with other libc functions that don't yet have nix wrappers.
862    /// Returns a reference to the underlying data type (as a sockaddr reference) along
863    /// with the size of the actual data type. sockaddr is commonly used as a proxy for
864    /// a superclass as C doesn't support inheritance, so many functions that take
865    /// a sockaddr * need to take the size of the underlying type as well and then internally cast it back.
866    pub fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
867        match *self {
868            SockAddr::Inet(InetAddr::V4(ref addr)) => (
869                // This cast is always allowed in C
870                unsafe {
871                    &*(addr as *const libc::sockaddr_in as *const libc::sockaddr)
872                },
873                mem::size_of_val(addr) as libc::socklen_t
874            ),
875            SockAddr::Inet(InetAddr::V6(ref addr)) => (
876                // This cast is always allowed in C
877                unsafe {
878                    &*(addr as *const libc::sockaddr_in6 as *const libc::sockaddr)
879                },
880                mem::size_of_val(addr) as libc::socklen_t
881            ),
882            SockAddr::Unix(UnixAddr { ref sun, path_len }) => (
883                // This cast is always allowed in C
884                unsafe {
885                    &*(sun as *const libc::sockaddr_un as *const libc::sockaddr)
886                },
887                (path_len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t
888            ),
889            #[cfg(any(target_os = "android", target_os = "linux"))]
890            SockAddr::Netlink(NetlinkAddr(ref sa)) => (
891                // This cast is always allowed in C
892                unsafe {
893                    &*(sa as *const libc::sockaddr_nl as *const libc::sockaddr)
894                },
895                mem::size_of_val(sa) as libc::socklen_t
896            ),
897            #[cfg(any(target_os = "android", target_os = "linux"))]
898            SockAddr::Alg(AlgAddr(ref sa)) => (
899                // This cast is always allowed in C
900                unsafe {
901                    &*(sa as *const libc::sockaddr_alg as *const libc::sockaddr)
902                },
903                mem::size_of_val(sa) as libc::socklen_t
904            ),
905            #[cfg(any(target_os = "ios", target_os = "macos"))]
906            SockAddr::SysControl(SysControlAddr(ref sa)) => (
907                // This cast is always allowed in C
908                unsafe {
909                    &*(sa as *const libc::sockaddr_ctl as *const libc::sockaddr)
910                },
911                mem::size_of_val(sa) as libc::socklen_t
912
913            ),
914            #[cfg(any(target_os = "android", target_os = "linux"))]
915            SockAddr::Link(LinkAddr(ref addr)) => (
916                // This cast is always allowed in C
917                unsafe {
918                    &*(addr as *const libc::sockaddr_ll as *const libc::sockaddr)
919                },
920                mem::size_of_val(addr) as libc::socklen_t
921            ),
922            #[cfg(any(target_os = "dragonfly",
923                      target_os = "freebsd",
924                      target_os = "ios",
925                      target_os = "macos",
926                      target_os = "illumos",
927                      target_os = "netbsd",
928                      target_os = "openbsd"))]
929            SockAddr::Link(LinkAddr(ref addr)) => (
930                // This cast is always allowed in C
931                unsafe {
932                    &*(addr as *const libc::sockaddr_dl as *const libc::sockaddr)
933                },
934                mem::size_of_val(addr) as libc::socklen_t
935            ),
936            #[cfg(any(target_os = "android", target_os = "linux"))]
937            SockAddr::Vsock(VsockAddr(ref sa)) => (
938                // This cast is always allowed in C
939                unsafe {
940                    &*(sa as *const libc::sockaddr_vm as *const libc::sockaddr)
941                },
942                mem::size_of_val(sa) as libc::socklen_t
943            ),
944        }
945    }
946}
947
948impl fmt::Display for SockAddr {
949    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
950        match *self {
951            SockAddr::Inet(ref inet) => inet.fmt(f),
952            SockAddr::Unix(ref unix) => unix.fmt(f),
953            #[cfg(any(target_os = "android", target_os = "linux"))]
954            SockAddr::Netlink(ref nl) => nl.fmt(f),
955            #[cfg(any(target_os = "android", target_os = "linux"))]
956            SockAddr::Alg(ref nl) => nl.fmt(f),
957            #[cfg(any(target_os = "ios", target_os = "macos"))]
958            SockAddr::SysControl(ref sc) => sc.fmt(f),
959            #[cfg(any(target_os = "android",
960                      target_os = "dragonfly",
961                      target_os = "freebsd",
962                      target_os = "ios",
963                      target_os = "linux",
964                      target_os = "macos",
965                      target_os = "netbsd",
966                      target_os = "illumos",
967                      target_os = "openbsd"))]
968            SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
969            #[cfg(any(target_os = "android", target_os = "linux"))]
970            SockAddr::Vsock(ref svm) => svm.fmt(f),
971        }
972    }
973}
974
975#[cfg(any(target_os = "android", target_os = "linux"))]
976pub mod netlink {
977    use crate::sys::socket::addr::AddressFamily;
978    use libc::{sa_family_t, sockaddr_nl};
979    use std::{fmt, mem};
980
981    #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
982    pub struct NetlinkAddr(pub sockaddr_nl);
983
984    impl NetlinkAddr {
985        pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
986            let mut addr: sockaddr_nl = unsafe { mem::zeroed() };
987            addr.nl_family = AddressFamily::Netlink as sa_family_t;
988            addr.nl_pid = pid;
989            addr.nl_groups = groups;
990
991            NetlinkAddr(addr)
992        }
993
994        pub const fn pid(&self) -> u32 {
995            self.0.nl_pid
996        }
997
998        pub const fn groups(&self) -> u32 {
999            self.0.nl_groups
1000        }
1001    }
1002
1003    impl fmt::Display for NetlinkAddr {
1004        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1005            write!(f, "pid: {} groups: {}", self.pid(), self.groups())
1006        }
1007    }
1008}
1009
1010#[cfg(any(target_os = "android", target_os = "linux"))]
1011pub mod alg {
1012    use libc::{AF_ALG, sockaddr_alg, c_char};
1013    use std::{fmt, mem, str};
1014    use std::hash::{Hash, Hasher};
1015    use std::ffi::CStr;
1016
1017    #[derive(Copy, Clone)]
1018    pub struct AlgAddr(pub sockaddr_alg);
1019
1020    // , PartialEq, Eq, Debug, Hash
1021    impl PartialEq for AlgAddr {
1022        fn eq(&self, other: &Self) -> bool {
1023            let (inner, other) = (self.0, other.0);
1024            (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]) ==
1025            (other.salg_family, &other.salg_type[..], other.salg_feat, other.salg_mask, &other.salg_name[..])
1026        }
1027    }
1028
1029    impl Eq for AlgAddr {}
1030
1031    impl Hash for AlgAddr {
1032        fn hash<H: Hasher>(&self, s: &mut H) {
1033            let inner = self.0;
1034            (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]).hash(s);
1035        }
1036    }
1037
1038    impl AlgAddr {
1039        pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
1040            let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
1041            addr.salg_family = AF_ALG as u16;
1042            addr.salg_type[..alg_type.len()].copy_from_slice(alg_type.to_string().as_bytes());
1043            addr.salg_name[..alg_name.len()].copy_from_slice(alg_name.to_string().as_bytes());
1044
1045            AlgAddr(addr)
1046        }
1047
1048
1049        pub fn alg_type(&self) -> &CStr {
1050            unsafe { CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char) }
1051        }
1052
1053        pub fn alg_name(&self) -> &CStr {
1054            unsafe { CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char) }
1055        }
1056    }
1057
1058    impl fmt::Display for AlgAddr {
1059        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1060            write!(f, "type: {} alg: {}",
1061                   self.alg_name().to_string_lossy(),
1062                   self.alg_type().to_string_lossy())
1063        }
1064    }
1065
1066    impl fmt::Debug for AlgAddr {
1067        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1068            fmt::Display::fmt(self, f)
1069        }
1070    }
1071}
1072
1073#[cfg(any(target_os = "ios", target_os = "macos"))]
1074pub mod sys_control {
1075    use crate::sys::socket::addr::AddressFamily;
1076    use libc::{self, c_uchar};
1077    use std::{fmt, mem};
1078    use std::os::unix::io::RawFd;
1079    use crate::{Errno, Result};
1080
1081    // FIXME: Move type into `libc`
1082    #[repr(C)]
1083    #[derive(Clone, Copy)]
1084    #[allow(missing_debug_implementations)]
1085    pub struct ctl_ioc_info {
1086        pub ctl_id: u32,
1087        pub ctl_name: [c_uchar; MAX_KCTL_NAME],
1088    }
1089
1090    const CTL_IOC_MAGIC: u8 = b'N';
1091    const CTL_IOC_INFO: u8 = 3;
1092    const MAX_KCTL_NAME: usize = 96;
1093
1094    ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info);
1095
1096    #[repr(C)]
1097    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1098    pub struct SysControlAddr(pub libc::sockaddr_ctl);
1099
1100    impl SysControlAddr {
1101        pub const fn new(id: u32, unit: u32) -> SysControlAddr {
1102            let addr = libc::sockaddr_ctl {
1103                sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
1104                sc_family: AddressFamily::System as c_uchar,
1105                ss_sysaddr: libc::AF_SYS_CONTROL as u16,
1106                sc_id: id,
1107                sc_unit: unit,
1108                sc_reserved: [0; 5]
1109            };
1110
1111            SysControlAddr(addr)
1112        }
1113
1114        pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
1115            if name.len() > MAX_KCTL_NAME {
1116                return Err(Errno::ENAMETOOLONG);
1117            }
1118
1119            let mut ctl_name = [0; MAX_KCTL_NAME];
1120            ctl_name[..name.len()].clone_from_slice(name.as_bytes());
1121            let mut info = ctl_ioc_info { ctl_id: 0, ctl_name };
1122
1123            unsafe { ctl_info(sockfd, &mut info)?; }
1124
1125            Ok(SysControlAddr::new(info.ctl_id, unit))
1126        }
1127
1128        pub const fn id(&self) -> u32 {
1129            self.0.sc_id
1130        }
1131
1132        pub const fn unit(&self) -> u32 {
1133            self.0.sc_unit
1134        }
1135    }
1136
1137    impl fmt::Display for SysControlAddr {
1138        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1139            fmt::Debug::fmt(self, f)
1140        }
1141    }
1142}
1143
1144
1145#[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
1146mod datalink {
1147    use super::{fmt, AddressFamily};
1148
1149    /// Hardware Address
1150    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1151    pub struct LinkAddr(pub libc::sockaddr_ll);
1152
1153    impl LinkAddr {
1154        /// Always AF_PACKET
1155        pub fn family(&self) -> AddressFamily {
1156            assert_eq!(self.0.sll_family as i32, libc::AF_PACKET);
1157            AddressFamily::Packet
1158        }
1159
1160        /// Physical-layer protocol
1161        pub fn protocol(&self) -> u16 {
1162            self.0.sll_protocol
1163        }
1164
1165        /// Interface number
1166        pub fn ifindex(&self) -> usize {
1167            self.0.sll_ifindex as usize
1168        }
1169
1170        /// ARP hardware type
1171        pub fn hatype(&self) -> u16 {
1172            self.0.sll_hatype
1173        }
1174
1175        /// Packet type
1176        pub fn pkttype(&self) -> u8 {
1177            self.0.sll_pkttype
1178        }
1179
1180        /// Length of MAC address
1181        pub fn halen(&self) -> usize {
1182            self.0.sll_halen as usize
1183        }
1184
1185        /// Physical-layer address (MAC)
1186        pub fn addr(&self) -> [u8; 6] {
1187            [
1188                self.0.sll_addr[0],
1189                self.0.sll_addr[1],
1190                self.0.sll_addr[2],
1191                self.0.sll_addr[3],
1192                self.0.sll_addr[4],
1193                self.0.sll_addr[5],
1194            ]
1195        }
1196    }
1197
1198    impl fmt::Display for LinkAddr {
1199        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1200            let addr = self.addr();
1201            write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1202                addr[0],
1203                addr[1],
1204                addr[2],
1205                addr[3],
1206                addr[4],
1207                addr[5])
1208        }
1209    }
1210}
1211
1212#[cfg(any(target_os = "dragonfly",
1213          target_os = "freebsd",
1214          target_os = "ios",
1215          target_os = "macos",
1216          target_os = "illumos",
1217          target_os = "netbsd",
1218          target_os = "openbsd"))]
1219mod datalink {
1220    use super::{fmt, AddressFamily};
1221
1222    /// Hardware Address
1223    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1224    pub struct LinkAddr(pub libc::sockaddr_dl);
1225
1226    impl LinkAddr {
1227        /// Total length of sockaddr
1228        #[cfg(not(target_os = "illumos"))]
1229        pub fn len(&self) -> usize {
1230            self.0.sdl_len as usize
1231        }
1232
1233        /// always == AF_LINK
1234        pub fn family(&self) -> AddressFamily {
1235            assert_eq!(i32::from(self.0.sdl_family), libc::AF_LINK);
1236            AddressFamily::Link
1237        }
1238
1239        /// interface index, if != 0, system given index for interface
1240        pub fn ifindex(&self) -> usize {
1241            self.0.sdl_index as usize
1242        }
1243
1244        /// Datalink type
1245        pub fn datalink_type(&self) -> u8 {
1246            self.0.sdl_type
1247        }
1248
1249        // MAC address start position
1250        pub fn nlen(&self) -> usize {
1251            self.0.sdl_nlen as usize
1252        }
1253
1254        /// link level address length
1255        pub fn alen(&self) -> usize {
1256            self.0.sdl_alen as usize
1257        }
1258
1259        /// link layer selector length
1260        pub fn slen(&self) -> usize {
1261            self.0.sdl_slen as usize
1262        }
1263
1264        /// if link level address length == 0,
1265        /// or `sdl_data` not be larger.
1266        pub fn is_empty(&self) -> bool {
1267            let nlen = self.nlen();
1268            let alen = self.alen();
1269            let data_len = self.0.sdl_data.len();
1270
1271            alen == 0 || nlen + alen >= data_len
1272        }
1273
1274        /// Physical-layer address (MAC)
1275        pub fn addr(&self) -> [u8; 6] {
1276            let nlen = self.nlen();
1277            let data = self.0.sdl_data;
1278
1279            assert!(!self.is_empty());
1280
1281            [
1282                data[nlen] as u8,
1283                data[nlen + 1] as u8,
1284                data[nlen + 2] as u8,
1285                data[nlen + 3] as u8,
1286                data[nlen + 4] as u8,
1287                data[nlen + 5] as u8,
1288            ]
1289        }
1290    }
1291
1292    impl fmt::Display for LinkAddr {
1293        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1294            let addr = self.addr();
1295            write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1296                addr[0],
1297                addr[1],
1298                addr[2],
1299                addr[3],
1300                addr[4],
1301                addr[5])
1302        }
1303    }
1304}
1305
1306#[cfg(any(target_os = "android", target_os = "linux"))]
1307pub mod vsock {
1308    use crate::sys::socket::addr::AddressFamily;
1309    use libc::{sa_family_t, sockaddr_vm};
1310    use std::{fmt, mem};
1311    use std::hash::{Hash, Hasher};
1312
1313    #[derive(Copy, Clone)]
1314    pub struct VsockAddr(pub sockaddr_vm);
1315
1316    impl PartialEq for VsockAddr {
1317        fn eq(&self, other: &Self) -> bool {
1318            let (inner, other) = (self.0, other.0);
1319            (inner.svm_family, inner.svm_cid, inner.svm_port) ==
1320            (other.svm_family, other.svm_cid, other.svm_port)
1321        }
1322    }
1323
1324    impl Eq for VsockAddr {}
1325
1326    impl Hash for VsockAddr {
1327        fn hash<H: Hasher>(&self, s: &mut H) {
1328            let inner = self.0;
1329            (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
1330        }
1331    }
1332
1333    /// VSOCK Address
1334    ///
1335    /// The address for AF_VSOCK socket is defined as a combination of a
1336    /// 32-bit Context Identifier (CID) and a 32-bit port number.
1337    impl VsockAddr {
1338        pub fn new(cid: u32, port: u32) -> VsockAddr {
1339            let mut addr: sockaddr_vm = unsafe { mem::zeroed() };
1340            addr.svm_family = AddressFamily::Vsock as sa_family_t;
1341            addr.svm_cid = cid;
1342            addr.svm_port = port;
1343
1344            VsockAddr(addr)
1345        }
1346
1347        /// Context Identifier (CID)
1348        pub fn cid(&self) -> u32 {
1349            self.0.svm_cid
1350        }
1351
1352        /// Port number
1353        pub fn port(&self) -> u32 {
1354            self.0.svm_port
1355        }
1356    }
1357
1358    impl fmt::Display for VsockAddr {
1359        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1360            write!(f, "cid: {} port: {}", self.cid(), self.port())
1361        }
1362    }
1363
1364    impl fmt::Debug for VsockAddr {
1365        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1366            fmt::Display::fmt(self, f)
1367        }
1368    }
1369}
1370
1371#[cfg(test)]
1372mod tests {
1373    #[cfg(any(target_os = "android",
1374              target_os = "dragonfly",
1375              target_os = "freebsd",
1376              target_os = "ios",
1377              target_os = "linux",
1378              target_os = "macos",
1379              target_os = "netbsd",
1380              target_os = "illumos",
1381              target_os = "openbsd"))]
1382    use super::*;
1383
1384    #[cfg(any(target_os = "dragonfly",
1385              target_os = "freebsd",
1386              target_os = "ios",
1387              target_os = "macos",
1388              target_os = "netbsd",
1389              target_os = "openbsd"))]
1390    #[test]
1391    fn test_macos_loopback_datalink_addr() {
1392        let bytes = [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
1393        let sa = bytes.as_ptr() as *const libc::sockaddr;
1394        let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
1395        assert!(_sock_addr.is_none());
1396    }
1397
1398    #[cfg(any(target_os = "dragonfly",
1399              target_os = "freebsd",
1400              target_os = "ios",
1401              target_os = "macos",
1402              target_os = "netbsd",
1403              target_os = "openbsd"))]
1404    #[test]
1405    fn test_macos_tap_datalink_addr() {
1406        let bytes = [20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35, 76, -80];
1407        let ptr = bytes.as_ptr();
1408        let sa = ptr as *const libc::sockaddr;
1409        let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
1410
1411        assert!(_sock_addr.is_some());
1412
1413        let sock_addr = _sock_addr.unwrap();
1414
1415        assert_eq!(sock_addr.family(), AddressFamily::Link);
1416
1417        match sock_addr {
1418            SockAddr::Link(ether_addr) => {
1419                assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]);
1420            },
1421            _ => { unreachable!() }
1422        };
1423    }
1424
1425    #[cfg(target_os = "illumos")]
1426    #[test]
1427    fn test_illumos_tap_datalink_addr() {
1428        let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176];
1429        let ptr = bytes.as_ptr();
1430        let sa = ptr as *const libc::sockaddr;
1431        let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
1432
1433        assert!(_sock_addr.is_some());
1434
1435        let sock_addr = _sock_addr.unwrap();
1436
1437        assert_eq!(sock_addr.family(), AddressFamily::Link);
1438
1439        match sock_addr {
1440            SockAddr::Link(ether_addr) => {
1441                assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]);
1442            },
1443            _ => { unreachable!() }
1444        };
1445    }
1446
1447    #[cfg(any(target_os = "android", target_os = "linux"))]
1448    #[test]
1449    fn test_abstract_sun_path() {
1450        let name = String::from("nix\0abstract\0test");
1451        let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
1452
1453        let sun_path1 = unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] };
1454        let sun_path2 = [0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116];
1455        assert_eq!(sun_path1, sun_path2);
1456    }
1457}