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