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