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