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