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