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