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