]> git.proxmox.com Git - rustc.git/blob - src/vendor/nix/src/sys/socket/addr.rs
New upstream version 1.23.0+dfsg1
[rustc.git] / src / vendor / nix / src / sys / socket / addr.rs
1 use super::{consts, sa_family_t};
2 use {Errno, Error, Result, NixPath};
3 use libc;
4 use std::{fmt, hash, mem, net, ptr};
5 use std::ffi::OsStr;
6 use std::path::Path;
7 use std::os::unix::ffi::OsStrExt;
8 #[cfg(any(target_os = "linux", target_os = "android"))]
9 use ::sys::socket::addr::netlink::NetlinkAddr;
10 #[cfg(any(target_os = "macos", target_os = "ios"))]
11 use std::os::unix::io::RawFd;
12 #[cfg(any(target_os = "macos", target_os = "ios"))]
13 use ::sys::socket::addr::sys_control::SysControlAddr;
14
15 // TODO: uncomment out IpAddr functions: rust-lang/rfcs#988
16
17 /*
18 *
19 * ===== AddressFamily =====
20 *
21 */
22
23 #[repr(i32)]
24 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
25 pub enum AddressFamily {
26 Unix = consts::AF_UNIX,
27 Inet = consts::AF_INET,
28 Inet6 = consts::AF_INET6,
29 #[cfg(any(target_os = "linux", target_os = "android"))]
30 Netlink = consts::AF_NETLINK,
31 #[cfg(any(target_os = "linux", target_os = "android"))]
32 Packet = consts::AF_PACKET,
33 #[cfg(any(target_os = "macos", target_os = "ios"))]
34 System = consts::AF_SYSTEM,
35 }
36
37 #[derive(Copy)]
38 pub enum InetAddr {
39 V4(libc::sockaddr_in),
40 V6(libc::sockaddr_in6),
41 }
42
43 impl InetAddr {
44 pub fn from_std(std: &net::SocketAddr) -> InetAddr {
45 match *std {
46 net::SocketAddr::V4(ref addr) => {
47 InetAddr::V4(libc::sockaddr_in {
48 sin_family: AddressFamily::Inet as sa_family_t,
49 sin_port: addr.port().to_be(), // network byte order
50 sin_addr: Ipv4Addr::from_std(addr.ip()).0,
51 .. unsafe { mem::zeroed() }
52 })
53 }
54 net::SocketAddr::V6(ref addr) => {
55 InetAddr::V6(libc::sockaddr_in6 {
56 sin6_family: AddressFamily::Inet6 as sa_family_t,
57 sin6_port: addr.port().to_be(), // network byte order
58 sin6_addr: Ipv6Addr::from_std(addr.ip()).0,
59 sin6_flowinfo: addr.flowinfo(), // host byte order
60 sin6_scope_id: addr.scope_id(), // host byte order
61 .. unsafe { mem::zeroed() }
62 })
63 }
64 }
65 }
66
67 pub fn new(ip: IpAddr, port: u16) -> InetAddr {
68 match ip {
69 IpAddr::V4(ref ip) => {
70 InetAddr::V4(libc::sockaddr_in {
71 sin_family: AddressFamily::Inet as sa_family_t,
72 sin_port: port.to_be(),
73 sin_addr: ip.0,
74 .. unsafe { mem::zeroed() }
75 })
76 }
77 IpAddr::V6(ref ip) => {
78 InetAddr::V6(libc::sockaddr_in6 {
79 sin6_family: AddressFamily::Inet6 as sa_family_t,
80 sin6_port: port.to_be(),
81 sin6_addr: ip.0,
82 .. unsafe { mem::zeroed() }
83 })
84 }
85 }
86 }
87 /// Gets the IP address associated with this socket address.
88 pub fn ip(&self) -> IpAddr {
89 match *self {
90 InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)),
91 InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)),
92 }
93 }
94
95 /// Gets the port number associated with this socket address
96 pub fn port(&self) -> u16 {
97 match *self {
98 InetAddr::V6(ref sa) => u16::from_be(sa.sin6_port),
99 InetAddr::V4(ref sa) => u16::from_be(sa.sin_port),
100 }
101 }
102
103 pub fn to_std(&self) -> net::SocketAddr {
104 match *self {
105 InetAddr::V4(ref sa) => net::SocketAddr::V4(
106 net::SocketAddrV4::new(
107 Ipv4Addr(sa.sin_addr).to_std(),
108 self.port())),
109 InetAddr::V6(ref sa) => net::SocketAddr::V6(
110 net::SocketAddrV6::new(
111 Ipv6Addr(sa.sin6_addr).to_std(),
112 self.port(),
113 sa.sin6_flowinfo,
114 sa.sin6_scope_id)),
115 }
116 }
117
118 pub fn to_str(&self) -> String {
119 format!("{}", self)
120 }
121 }
122
123 impl PartialEq for InetAddr {
124 fn eq(&self, other: &InetAddr) -> bool {
125 match (*self, *other) {
126 (InetAddr::V4(ref a), InetAddr::V4(ref b)) => {
127 a.sin_port == b.sin_port &&
128 a.sin_addr.s_addr == b.sin_addr.s_addr
129 }
130 (InetAddr::V6(ref a), InetAddr::V6(ref b)) => {
131 a.sin6_port == b.sin6_port &&
132 a.sin6_addr.s6_addr == b.sin6_addr.s6_addr &&
133 a.sin6_flowinfo == b.sin6_flowinfo &&
134 a.sin6_scope_id == b.sin6_scope_id
135 }
136 _ => false,
137 }
138 }
139 }
140
141 impl Eq for InetAddr {
142 }
143
144 impl hash::Hash for InetAddr {
145 fn hash<H: hash::Hasher>(&self, s: &mut H) {
146 match *self {
147 InetAddr::V4(ref a) => {
148 ( a.sin_family,
149 a.sin_port,
150 a.sin_addr.s_addr ).hash(s)
151 }
152 InetAddr::V6(ref a) => {
153 ( a.sin6_family,
154 a.sin6_port,
155 &a.sin6_addr.s6_addr,
156 a.sin6_flowinfo,
157 a.sin6_scope_id ).hash(s)
158 }
159 }
160 }
161 }
162
163 impl Clone for InetAddr {
164 fn clone(&self) -> InetAddr {
165 *self
166 }
167 }
168
169 impl fmt::Display for InetAddr {
170 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171 match *self {
172 InetAddr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()),
173 InetAddr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()),
174 }
175 }
176 }
177
178 /*
179 *
180 * ===== IpAddr =====
181 *
182 */
183
184 pub enum IpAddr {
185 V4(Ipv4Addr),
186 V6(Ipv6Addr),
187 }
188
189 impl IpAddr {
190 /// Create a new IpAddr that contains an IPv4 address.
191 ///
192 /// The result will represent the IP address a.b.c.d
193 pub fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr {
194 IpAddr::V4(Ipv4Addr::new(a, b, c, d))
195 }
196
197 /// Create a new IpAddr that contains an IPv6 address.
198 ///
199 /// The result will represent the IP address a:b:c:d:e:f
200 pub fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
201 IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
202 }
203
204 /*
205 pub fn from_std(std: &net::IpAddr) -> IpAddr {
206 match *std {
207 net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)),
208 net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)),
209 }
210 }
211
212 pub fn to_std(&self) -> net::IpAddr {
213 match *self {
214 IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()),
215 IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()),
216 }
217 }
218 */
219 }
220
221 impl fmt::Display for IpAddr {
222 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
223 match *self {
224 IpAddr::V4(ref v4) => v4.fmt(f),
225 IpAddr::V6(ref v6) => v6.fmt(f)
226 }
227 }
228 }
229
230 /*
231 *
232 * ===== Ipv4Addr =====
233 *
234 */
235
236 #[derive(Copy)]
237 pub struct Ipv4Addr(pub libc::in_addr);
238
239 impl Ipv4Addr {
240 pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
241 let ip = (((a as u32) << 24) |
242 ((b as u32) << 16) |
243 ((c as u32) << 8) |
244 ((d as u32) << 0)).to_be();
245
246 Ipv4Addr(libc::in_addr { s_addr: ip })
247 }
248
249 pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr {
250 let bits = std.octets();
251 Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
252 }
253
254 pub fn any() -> Ipv4Addr {
255 Ipv4Addr(libc::in_addr { s_addr: consts::INADDR_ANY })
256 }
257
258 pub fn octets(&self) -> [u8; 4] {
259 let bits = u32::from_be(self.0.s_addr);
260 [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
261 }
262
263 pub fn to_std(&self) -> net::Ipv4Addr {
264 let bits = self.octets();
265 net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
266 }
267 }
268
269 impl PartialEq for Ipv4Addr {
270 fn eq(&self, other: &Ipv4Addr) -> bool {
271 self.0.s_addr == other.0.s_addr
272 }
273 }
274
275 impl Eq for Ipv4Addr {
276 }
277
278 impl hash::Hash for Ipv4Addr {
279 fn hash<H: hash::Hasher>(&self, s: &mut H) {
280 self.0.s_addr.hash(s)
281 }
282 }
283
284 impl Clone for Ipv4Addr {
285 fn clone(&self) -> Ipv4Addr {
286 *self
287 }
288 }
289
290 impl fmt::Display for Ipv4Addr {
291 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
292 let octets = self.octets();
293 write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
294 }
295 }
296
297 /*
298 *
299 * ===== Ipv6Addr =====
300 *
301 */
302
303 #[derive(Clone, Copy)]
304 pub struct Ipv6Addr(pub libc::in6_addr);
305
306 // Note that IPv6 addresses are stored in big endian order on all architectures.
307 // See https://tools.ietf.org/html/rfc1700 or consult your favorite search
308 // engine.
309
310 macro_rules! to_u8_array {
311 ($($num:ident),*) => {
312 [ $(($num>>8) as u8, ($num&0xff) as u8,)* ]
313 }
314 }
315
316 macro_rules! to_u16_array {
317 ($slf:ident, $($first:expr, $second:expr),*) => {
318 [$( (($slf.0.s6_addr[$first] as u16) << 8) + $slf.0.s6_addr[$second] as u16,)*]
319 }
320 }
321
322 impl Ipv6Addr {
323 pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
324 let mut in6_addr_var: libc::in6_addr = unsafe{mem::uninitialized()};
325 in6_addr_var.s6_addr = to_u8_array!(a,b,c,d,e,f,g,h);
326 Ipv6Addr(in6_addr_var)
327 }
328
329 pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr {
330 let s = std.segments();
331 Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
332 }
333
334 /// Return the eight 16-bit segments that make up this address
335 pub fn segments(&self) -> [u16; 8] {
336 to_u16_array!(self, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
337 }
338
339 pub fn to_std(&self) -> net::Ipv6Addr {
340 let s = self.segments();
341 net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
342 }
343 }
344
345 impl fmt::Display for Ipv6Addr {
346 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
347 self.to_std().fmt(fmt)
348 }
349 }
350
351 /*
352 *
353 * ===== UnixAddr =====
354 *
355 */
356
357 /// A wrapper around `sockaddr_un`. We track the length of `sun_path` (excluding
358 /// a terminating null), because it may not be null-terminated. For example,
359 /// unconnected and Linux abstract sockets are never null-terminated, and POSIX
360 /// does not require that `sun_len` include the terminating null even for normal
361 /// sockets. Note that the actual sockaddr length is greater by
362 /// `offset_of!(libc::sockaddr_un, sun_path)`
363 #[derive(Copy)]
364 pub struct UnixAddr(pub libc::sockaddr_un, pub usize);
365
366 impl UnixAddr {
367 /// Create a new sockaddr_un representing a filesystem path.
368 pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
369 try!(path.with_nix_path(|cstr| {
370 unsafe {
371 let mut ret = libc::sockaddr_un {
372 sun_family: AddressFamily::Unix as sa_family_t,
373 .. mem::zeroed()
374 };
375
376 let bytes = cstr.to_bytes();
377
378 if bytes.len() > ret.sun_path.len() {
379 return Err(Error::Sys(Errno::ENAMETOOLONG));
380 }
381
382 ptr::copy_nonoverlapping(bytes.as_ptr(),
383 ret.sun_path.as_mut_ptr() as *mut u8,
384 bytes.len());
385
386 Ok(UnixAddr(ret, bytes.len()))
387 }
388 }))
389 }
390
391 /// Create a new sockaddr_un representing an address in the
392 /// "abstract namespace". This is a Linux-specific extension,
393 /// primarily used to allow chrooted processes to communicate with
394 /// specific daemons.
395 pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
396 unsafe {
397 let mut ret = libc::sockaddr_un {
398 sun_family: AddressFamily::Unix as sa_family_t,
399 .. mem::zeroed()
400 };
401
402 if path.len() + 1 > ret.sun_path.len() {
403 return Err(Error::Sys(Errno::ENAMETOOLONG));
404 }
405
406 // Abstract addresses are represented by sun_path[0] ==
407 // b'\0', so copy starting one byte in.
408 ptr::copy_nonoverlapping(path.as_ptr(),
409 ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
410 path.len());
411
412 Ok(UnixAddr(ret, path.len() + 1))
413 }
414 }
415
416 fn sun_path(&self) -> &[u8] {
417 unsafe { mem::transmute(&self.0.sun_path[..self.1]) }
418 }
419
420 /// If this address represents a filesystem path, return that path.
421 pub fn path(&self) -> Option<&Path> {
422 if self.1 == 0 || self.0.sun_path[0] == 0 {
423 // unbound or abstract
424 None
425 } else {
426 let p = self.sun_path();
427 // POSIX only requires that `sun_len` be at least long enough to
428 // contain the pathname, and it need not be null-terminated. So we
429 // need to create a string that is the shorter of the
430 // null-terminated length or the full length.
431 let ptr = &self.0.sun_path as *const libc::c_char;
432 let reallen = unsafe { libc::strnlen(ptr, p.len()) };
433 Some(Path::new(<OsStr as OsStrExt>::from_bytes(&p[..reallen])))
434 }
435 }
436 }
437
438 impl PartialEq for UnixAddr {
439 fn eq(&self, other: &UnixAddr) -> bool {
440 self.sun_path() == other.sun_path()
441 }
442 }
443
444 impl Eq for UnixAddr {
445 }
446
447 impl hash::Hash for UnixAddr {
448 fn hash<H: hash::Hasher>(&self, s: &mut H) {
449 ( self.0.sun_family, self.sun_path() ).hash(s)
450 }
451 }
452
453 impl Clone for UnixAddr {
454 fn clone(&self) -> UnixAddr {
455 *self
456 }
457 }
458
459 impl fmt::Display for UnixAddr {
460 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
461 if self.1 == 0 {
462 f.write_str("<unbound UNIX socket>")
463 } else if let Some(path) = self.path() {
464 path.display().fmt(f)
465 } else {
466 let display = String::from_utf8_lossy(&self.sun_path()[1..]);
467 write!(f, "@{}", display)
468 }
469 }
470 }
471
472 /*
473 *
474 * ===== Sock addr =====
475 *
476 */
477
478 /// Represents a socket address
479 #[derive(Copy)]
480 pub enum SockAddr {
481 Inet(InetAddr),
482 Unix(UnixAddr),
483 #[cfg(any(target_os = "linux", target_os = "android"))]
484 Netlink(NetlinkAddr),
485 #[cfg(any(target_os = "macos", target_os = "ios"))]
486 SysControl(SysControlAddr),
487 }
488
489 impl SockAddr {
490 pub fn new_inet(addr: InetAddr) -> SockAddr {
491 SockAddr::Inet(addr)
492 }
493
494 pub fn new_unix<P: ?Sized + NixPath>(path: &P) -> Result<SockAddr> {
495 Ok(SockAddr::Unix(try!(UnixAddr::new(path))))
496 }
497
498 #[cfg(any(target_os = "linux", target_os = "android"))]
499 pub fn new_netlink(pid: u32, groups: u32) -> SockAddr {
500 SockAddr::Netlink(NetlinkAddr::new(pid, groups))
501 }
502
503 #[cfg(any(target_os = "macos", target_os = "ios"))]
504 pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> {
505 SysControlAddr::from_name(sockfd, name, unit).map(|a| SockAddr::SysControl(a))
506 }
507
508 pub fn family(&self) -> AddressFamily {
509 match *self {
510 SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
511 SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6,
512 SockAddr::Unix(..) => AddressFamily::Unix,
513 #[cfg(any(target_os = "linux", target_os = "android"))]
514 SockAddr::Netlink(..) => AddressFamily::Netlink,
515 #[cfg(any(target_os = "macos", target_os = "ios"))]
516 SockAddr::SysControl(..) => AddressFamily::System,
517 }
518 }
519
520 pub fn to_str(&self) -> String {
521 format!("{}", self)
522 }
523
524 pub unsafe fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
525 match *self {
526 SockAddr::Inet(InetAddr::V4(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in>() as libc::socklen_t),
527 SockAddr::Inet(InetAddr::V6(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t),
528 SockAddr::Unix(UnixAddr(ref addr, len)) => (mem::transmute(addr), (len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t),
529 #[cfg(any(target_os = "linux", target_os = "android"))]
530 SockAddr::Netlink(NetlinkAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t),
531 #[cfg(any(target_os = "macos", target_os = "ios"))]
532 SockAddr::SysControl(SysControlAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<sys_control::sockaddr_ctl>() as libc::socklen_t),
533 }
534 }
535 }
536
537 impl PartialEq for SockAddr {
538 fn eq(&self, other: &SockAddr) -> bool {
539 match (*self, *other) {
540 (SockAddr::Inet(ref a), SockAddr::Inet(ref b)) => {
541 a == b
542 }
543 (SockAddr::Unix(ref a), SockAddr::Unix(ref b)) => {
544 a == b
545 }
546 #[cfg(any(target_os = "linux", target_os = "android"))]
547 (SockAddr::Netlink(ref a), SockAddr::Netlink(ref b)) => {
548 a == b
549 }
550 _ => false,
551 }
552 }
553 }
554
555 impl Eq for SockAddr {
556 }
557
558 impl hash::Hash for SockAddr {
559 fn hash<H: hash::Hasher>(&self, s: &mut H) {
560 match *self {
561 SockAddr::Inet(ref a) => a.hash(s),
562 SockAddr::Unix(ref a) => a.hash(s),
563 #[cfg(any(target_os = "linux", target_os = "android"))]
564 SockAddr::Netlink(ref a) => a.hash(s),
565 #[cfg(any(target_os = "macos", target_os = "ios"))]
566 SockAddr::SysControl(ref a) => a.hash(s),
567 }
568 }
569 }
570
571 impl Clone for SockAddr {
572 fn clone(&self) -> SockAddr {
573 *self
574 }
575 }
576
577 impl fmt::Display for SockAddr {
578 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
579 match *self {
580 SockAddr::Inet(ref inet) => inet.fmt(f),
581 SockAddr::Unix(ref unix) => unix.fmt(f),
582 #[cfg(any(target_os = "linux", target_os = "android"))]
583 SockAddr::Netlink(ref nl) => nl.fmt(f),
584 #[cfg(any(target_os = "macos", target_os = "ios"))]
585 SockAddr::SysControl(ref sc) => sc.fmt(f),
586 }
587 }
588 }
589
590 #[cfg(any(target_os = "linux", target_os = "android"))]
591 pub mod netlink {
592 use ::sys::socket::addr::{AddressFamily};
593 use libc::{sa_family_t, sockaddr_nl};
594 use std::{fmt, mem};
595 use std::hash::{Hash, Hasher};
596
597 #[derive(Copy, Clone)]
598 pub struct NetlinkAddr(pub sockaddr_nl);
599
600 // , PartialEq, Eq, Debug, Hash
601 impl PartialEq for NetlinkAddr {
602 fn eq(&self, other: &Self) -> bool {
603 let (inner, other) = (self.0, other.0);
604 (inner.nl_family, inner.nl_pid, inner.nl_groups) ==
605 (other.nl_family, other.nl_pid, other.nl_groups)
606 }
607 }
608
609 impl Eq for NetlinkAddr {}
610
611 impl Hash for NetlinkAddr {
612 fn hash<H: Hasher>(&self, s: &mut H) {
613 let inner = self.0;
614 (inner.nl_family, inner.nl_pid, inner.nl_groups).hash(s);
615 }
616 }
617
618
619 impl NetlinkAddr {
620 pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
621 let mut addr: sockaddr_nl = unsafe { mem::zeroed() };
622 addr.nl_family = AddressFamily::Netlink as sa_family_t;
623 addr.nl_pid = pid;
624 addr.nl_groups = groups;
625
626 NetlinkAddr(addr)
627 }
628
629 pub fn pid(&self) -> u32 {
630 self.0.nl_pid
631 }
632
633 pub fn groups(&self) -> u32 {
634 self.0.nl_groups
635 }
636 }
637
638 impl fmt::Display for NetlinkAddr {
639 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
640 write!(f, "pid: {} groups: {}", self.pid(), self.groups())
641 }
642 }
643 }
644
645 #[cfg(any(target_os = "macos", target_os = "ios"))]
646 pub mod sys_control {
647 use ::sys::socket::consts;
648 use ::sys::socket::addr::{AddressFamily};
649 use libc::{c_uchar, uint16_t, uint32_t};
650 use std::{fmt, mem};
651 use std::hash::{Hash, Hasher};
652 use std::os::unix::io::RawFd;
653 use {Errno, Error, Result};
654
655 #[repr(C)]
656 pub struct ctl_ioc_info {
657 pub ctl_id: uint32_t,
658 pub ctl_name: [c_uchar; MAX_KCTL_NAME],
659 }
660
661 const CTL_IOC_MAGIC: u8 = 'N' as u8;
662 const CTL_IOC_INFO: u8 = 3;
663 const MAX_KCTL_NAME: usize = 96;
664
665 ioctl!(readwrite ctl_info with CTL_IOC_MAGIC, CTL_IOC_INFO; ctl_ioc_info);
666
667 #[repr(C)]
668 #[derive(Copy, Clone)]
669 pub struct sockaddr_ctl {
670 pub sc_len: c_uchar,
671 pub sc_family: c_uchar,
672 pub ss_sysaddr: uint16_t,
673 pub sc_id: uint32_t,
674 pub sc_unit: uint32_t,
675 pub sc_reserved: [uint32_t; 5],
676 }
677
678 #[derive(Copy, Clone)]
679 pub struct SysControlAddr(pub sockaddr_ctl);
680
681 // , PartialEq, Eq, Debug, Hash
682 impl PartialEq for SysControlAddr {
683 fn eq(&self, other: &Self) -> bool {
684 let (inner, other) = (self.0, other.0);
685 (inner.sc_id, inner.sc_unit) ==
686 (other.sc_id, other.sc_unit)
687 }
688 }
689
690 impl Eq for SysControlAddr {}
691
692 impl Hash for SysControlAddr {
693 fn hash<H: Hasher>(&self, s: &mut H) {
694 let inner = self.0;
695 (inner.sc_id, inner.sc_unit).hash(s);
696 }
697 }
698
699
700 impl SysControlAddr {
701 pub fn new(id: u32, unit: u32) -> SysControlAddr {
702 let addr = sockaddr_ctl {
703 sc_len: mem::size_of::<sockaddr_ctl>() as c_uchar,
704 sc_family: AddressFamily::System as c_uchar,
705 ss_sysaddr: consts::AF_SYS_CONTROL as uint16_t,
706 sc_id: id,
707 sc_unit: unit,
708 sc_reserved: [0; 5]
709 };
710
711 SysControlAddr(addr)
712 }
713
714 pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
715 if name.len() > MAX_KCTL_NAME {
716 return Err(Error::Sys(Errno::ENAMETOOLONG));
717 }
718
719 let mut ctl_name = [0; MAX_KCTL_NAME];
720 ctl_name[..name.len()].clone_from_slice(name.as_bytes());
721 let mut info = ctl_ioc_info { ctl_id: 0, ctl_name: ctl_name };
722
723 unsafe { try!(ctl_info(sockfd, &mut info)); }
724
725 Ok(SysControlAddr::new(info.ctl_id, unit))
726 }
727
728 pub fn id(&self) -> u32 {
729 self.0.sc_id
730 }
731
732 pub fn unit(&self) -> u32 {
733 self.0.sc_unit
734 }
735 }
736
737 impl fmt::Display for SysControlAddr {
738 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
739 write!(f, "id: {} unit: {}", self.id(), self.unit())
740 }
741 }
742 }