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