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 target_os = "fuchsia"))] 26 pub use self::datalink::LinkAddr; 27 #[cfg(any(target_os = "android", 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", target_os = "fuchsia"))] 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(any(target_os = "android", 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(any(target_os = "android", 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(any(target_os = "android", 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(any(target_os = "android", 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(any(target_os = "android", 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. 717 /// 718 /// # Safety 719 /// 720 /// unsafe because it takes a raw pointer as argument. The caller must 721 /// ensure that the pointer is valid. 722 #[cfg(not(target_os = "fuchsia"))] from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr>723 pub(crate) unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr> { 724 if addr.is_null() { 725 None 726 } else { 727 match AddressFamily::from_i32(i32::from((*addr).sa_family)) { 728 Some(AddressFamily::Unix) => None, 729 Some(AddressFamily::Inet) => Some(SockAddr::Inet( 730 InetAddr::V4(*(addr as *const libc::sockaddr_in)))), 731 Some(AddressFamily::Inet6) => Some(SockAddr::Inet( 732 InetAddr::V6(*(addr as *const libc::sockaddr_in6)))), 733 #[cfg(any(target_os = "android", target_os = "linux"))] 734 Some(AddressFamily::Netlink) => Some(SockAddr::Netlink( 735 NetlinkAddr(*(addr as *const libc::sockaddr_nl)))), 736 #[cfg(any(target_os = "ios", target_os = "macos"))] 737 Some(AddressFamily::System) => Some(SockAddr::SysControl( 738 SysControlAddr(*(addr as *const libc::sockaddr_ctl)))), 739 #[cfg(any(target_os = "android", target_os = "linux"))] 740 Some(AddressFamily::Packet) => Some(SockAddr::Link( 741 LinkAddr(*(addr as *const libc::sockaddr_ll)))), 742 #[cfg(any(target_os = "dragonfly", 743 target_os = "freebsd", 744 target_os = "ios", 745 target_os = "macos", 746 target_os = "netbsd", 747 target_os = "openbsd"))] 748 Some(AddressFamily::Link) => { 749 let ether_addr = LinkAddr(*(addr as *const libc::sockaddr_dl)); 750 if ether_addr.is_empty() { 751 None 752 } else { 753 Some(SockAddr::Link(ether_addr)) 754 } 755 }, 756 #[cfg(any(target_os = "android", target_os = "linux"))] 757 Some(AddressFamily::Vsock) => Some(SockAddr::Vsock( 758 VsockAddr(*(addr as *const libc::sockaddr_vm)))), 759 // Other address families are currently not supported and simply yield a None 760 // entry instead of a proper conversion to a `SockAddr`. 761 Some(_) | None => None, 762 } 763 } 764 } 765 766 /// Conversion from nix's SockAddr type to the underlying libc sockaddr type. 767 /// 768 /// This is useful for interfacing with other libc functions that don't yet have nix wrappers. 769 /// Returns a reference to the underlying data type (as a sockaddr reference) along 770 /// with the size of the actual data type. sockaddr is commonly used as a proxy for 771 /// a superclass as C doesn't support inheritance, so many functions that take 772 /// 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)773 pub fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) { 774 match *self { 775 SockAddr::Inet(InetAddr::V4(ref addr)) => ( 776 // This cast is always allowed in C 777 unsafe { 778 &*(addr as *const libc::sockaddr_in as *const libc::sockaddr) 779 }, 780 mem::size_of_val(addr) as libc::socklen_t 781 ), 782 SockAddr::Inet(InetAddr::V6(ref addr)) => ( 783 // This cast is always allowed in C 784 unsafe { 785 &*(addr as *const libc::sockaddr_in6 as *const libc::sockaddr) 786 }, 787 mem::size_of_val(addr) as libc::socklen_t 788 ), 789 SockAddr::Unix(UnixAddr(ref addr, len)) => ( 790 // This cast is always allowed in C 791 unsafe { 792 &*(addr as *const libc::sockaddr_un as *const libc::sockaddr) 793 }, 794 (len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t 795 ), 796 #[cfg(any(target_os = "android", target_os = "linux"))] 797 SockAddr::Netlink(NetlinkAddr(ref sa)) => ( 798 // This cast is always allowed in C 799 unsafe { 800 &*(sa as *const libc::sockaddr_nl as *const libc::sockaddr) 801 }, 802 mem::size_of_val(sa) as libc::socklen_t 803 ), 804 #[cfg(any(target_os = "android", target_os = "linux"))] 805 SockAddr::Alg(AlgAddr(ref sa)) => ( 806 // This cast is always allowed in C 807 unsafe { 808 &*(sa as *const libc::sockaddr_alg as *const libc::sockaddr) 809 }, 810 mem::size_of_val(sa) as libc::socklen_t 811 ), 812 #[cfg(any(target_os = "ios", target_os = "macos"))] 813 SockAddr::SysControl(SysControlAddr(ref sa)) => ( 814 // This cast is always allowed in C 815 unsafe { 816 &*(sa as *const libc::sockaddr_ctl as *const libc::sockaddr) 817 }, 818 mem::size_of_val(sa) as libc::socklen_t 819 820 ), 821 #[cfg(any(target_os = "android", target_os = "linux"))] 822 SockAddr::Link(LinkAddr(ref addr)) => ( 823 // This cast is always allowed in C 824 unsafe { 825 &*(addr as *const libc::sockaddr_ll as *const libc::sockaddr) 826 }, 827 mem::size_of_val(addr) as libc::socklen_t 828 ), 829 #[cfg(any(target_os = "dragonfly", 830 target_os = "freebsd", 831 target_os = "ios", 832 target_os = "macos", 833 target_os = "netbsd", 834 target_os = "openbsd"))] 835 SockAddr::Link(LinkAddr(ref addr)) => ( 836 // This cast is always allowed in C 837 unsafe { 838 &*(addr as *const libc::sockaddr_dl as *const libc::sockaddr) 839 }, 840 mem::size_of_val(addr) as libc::socklen_t 841 ), 842 #[cfg(any(target_os = "android", target_os = "linux"))] 843 SockAddr::Vsock(VsockAddr(ref sa)) => ( 844 // This cast is always allowed in C 845 unsafe { 846 &*(sa as *const libc::sockaddr_vm as *const libc::sockaddr) 847 }, 848 mem::size_of_val(sa) as libc::socklen_t 849 ), 850 } 851 } 852 } 853 854 impl fmt::Display for SockAddr { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result855 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 856 match *self { 857 SockAddr::Inet(ref inet) => inet.fmt(f), 858 SockAddr::Unix(ref unix) => unix.fmt(f), 859 #[cfg(any(target_os = "android", target_os = "linux"))] 860 SockAddr::Netlink(ref nl) => nl.fmt(f), 861 #[cfg(any(target_os = "android", target_os = "linux"))] 862 SockAddr::Alg(ref nl) => nl.fmt(f), 863 #[cfg(any(target_os = "ios", target_os = "macos"))] 864 SockAddr::SysControl(ref sc) => sc.fmt(f), 865 #[cfg(any(target_os = "android", 866 target_os = "dragonfly", 867 target_os = "freebsd", 868 target_os = "ios", 869 target_os = "linux", 870 target_os = "macos", 871 target_os = "netbsd", 872 target_os = "openbsd"))] 873 SockAddr::Link(ref ether_addr) => ether_addr.fmt(f), 874 #[cfg(any(target_os = "android", target_os = "linux"))] 875 SockAddr::Vsock(ref svm) => svm.fmt(f), 876 } 877 } 878 } 879 880 #[cfg(any(target_os = "android", target_os = "linux"))] 881 pub mod netlink { 882 use crate::sys::socket::addr::AddressFamily; 883 use libc::{sa_family_t, sockaddr_nl}; 884 use std::{fmt, mem}; 885 886 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] 887 pub struct NetlinkAddr(pub sockaddr_nl); 888 889 impl NetlinkAddr { new(pid: u32, groups: u32) -> NetlinkAddr890 pub fn new(pid: u32, groups: u32) -> NetlinkAddr { 891 let mut addr: sockaddr_nl = unsafe { mem::zeroed() }; 892 addr.nl_family = AddressFamily::Netlink as sa_family_t; 893 addr.nl_pid = pid; 894 addr.nl_groups = groups; 895 896 NetlinkAddr(addr) 897 } 898 pid(&self) -> u32899 pub fn pid(&self) -> u32 { 900 self.0.nl_pid 901 } 902 groups(&self) -> u32903 pub fn groups(&self) -> u32 { 904 self.0.nl_groups 905 } 906 } 907 908 impl fmt::Display for NetlinkAddr { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result909 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 910 write!(f, "pid: {} groups: {}", self.pid(), self.groups()) 911 } 912 } 913 } 914 915 #[cfg(any(target_os = "android", target_os = "linux"))] 916 pub mod alg { 917 use libc::{AF_ALG, sockaddr_alg, c_char}; 918 use std::{fmt, mem, str}; 919 use std::hash::{Hash, Hasher}; 920 use std::ffi::CStr; 921 922 #[derive(Copy, Clone)] 923 pub struct AlgAddr(pub sockaddr_alg); 924 925 // , PartialEq, Eq, Debug, Hash 926 impl PartialEq for AlgAddr { eq(&self, other: &Self) -> bool927 fn eq(&self, other: &Self) -> bool { 928 let (inner, other) = (self.0, other.0); 929 (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]) == 930 (other.salg_family, &other.salg_type[..], other.salg_feat, other.salg_mask, &other.salg_name[..]) 931 } 932 } 933 934 impl Eq for AlgAddr {} 935 936 impl Hash for AlgAddr { hash<H: Hasher>(&self, s: &mut H)937 fn hash<H: Hasher>(&self, s: &mut H) { 938 let inner = self.0; 939 (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]).hash(s); 940 } 941 } 942 943 impl AlgAddr { new(alg_type: &str, alg_name: &str) -> AlgAddr944 pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr { 945 let mut addr: sockaddr_alg = unsafe { mem::zeroed() }; 946 addr.salg_family = AF_ALG as u16; 947 addr.salg_type[..alg_type.len()].copy_from_slice(alg_type.to_string().as_bytes()); 948 addr.salg_name[..alg_name.len()].copy_from_slice(alg_name.to_string().as_bytes()); 949 950 AlgAddr(addr) 951 } 952 953 alg_type(&self) -> &CStr954 pub fn alg_type(&self) -> &CStr { 955 unsafe { CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char) } 956 } 957 alg_name(&self) -> &CStr958 pub fn alg_name(&self) -> &CStr { 959 unsafe { CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char) } 960 } 961 } 962 963 impl fmt::Display for AlgAddr { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result964 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 965 write!(f, "type: {} alg: {}", 966 self.alg_name().to_string_lossy(), 967 self.alg_type().to_string_lossy()) 968 } 969 } 970 971 impl fmt::Debug for AlgAddr { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result972 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 973 fmt::Display::fmt(self, f) 974 } 975 } 976 } 977 978 #[cfg(any(target_os = "ios", target_os = "macos"))] 979 pub mod sys_control { 980 use crate::sys::socket::addr::AddressFamily; 981 use libc::{self, c_uchar}; 982 use std::{fmt, mem}; 983 use std::os::unix::io::RawFd; 984 use crate::{Errno, Error, Result}; 985 986 // FIXME: Move type into `libc` 987 #[repr(C)] 988 #[derive(Clone, Copy)] 989 #[allow(missing_debug_implementations)] 990 pub struct ctl_ioc_info { 991 pub ctl_id: u32, 992 pub ctl_name: [c_uchar; MAX_KCTL_NAME], 993 } 994 995 const CTL_IOC_MAGIC: u8 = 'N' as u8; 996 const CTL_IOC_INFO: u8 = 3; 997 const MAX_KCTL_NAME: usize = 96; 998 999 ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info); 1000 1001 #[repr(C)] 1002 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 1003 pub struct SysControlAddr(pub libc::sockaddr_ctl); 1004 1005 impl SysControlAddr { new(id: u32, unit: u32) -> SysControlAddr1006 pub fn new(id: u32, unit: u32) -> SysControlAddr { 1007 let addr = libc::sockaddr_ctl { 1008 sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar, 1009 sc_family: AddressFamily::System as c_uchar, 1010 ss_sysaddr: libc::AF_SYS_CONTROL as u16, 1011 sc_id: id, 1012 sc_unit: unit, 1013 sc_reserved: [0; 5] 1014 }; 1015 1016 SysControlAddr(addr) 1017 } 1018 from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr>1019 pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> { 1020 if name.len() > MAX_KCTL_NAME { 1021 return Err(Error::Sys(Errno::ENAMETOOLONG)); 1022 } 1023 1024 let mut ctl_name = [0; MAX_KCTL_NAME]; 1025 ctl_name[..name.len()].clone_from_slice(name.as_bytes()); 1026 let mut info = ctl_ioc_info { ctl_id: 0, ctl_name }; 1027 1028 unsafe { ctl_info(sockfd, &mut info)?; } 1029 1030 Ok(SysControlAddr::new(info.ctl_id, unit)) 1031 } 1032 id(&self) -> u321033 pub fn id(&self) -> u32 { 1034 self.0.sc_id 1035 } 1036 unit(&self) -> u321037 pub fn unit(&self) -> u32 { 1038 self.0.sc_unit 1039 } 1040 } 1041 1042 impl fmt::Display for SysControlAddr { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1043 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1044 fmt::Debug::fmt(self, f) 1045 } 1046 } 1047 } 1048 1049 1050 #[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))] 1051 mod datalink { 1052 use super::{fmt, AddressFamily}; 1053 1054 /// Hardware Address 1055 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 1056 pub struct LinkAddr(pub libc::sockaddr_ll); 1057 1058 impl LinkAddr { 1059 /// Always AF_PACKET family(&self) -> AddressFamily1060 pub fn family(&self) -> AddressFamily { 1061 assert_eq!(self.0.sll_family as i32, libc::AF_PACKET); 1062 AddressFamily::Packet 1063 } 1064 1065 /// Physical-layer protocol protocol(&self) -> u161066 pub fn protocol(&self) -> u16 { 1067 self.0.sll_protocol 1068 } 1069 1070 /// Interface number ifindex(&self) -> usize1071 pub fn ifindex(&self) -> usize { 1072 self.0.sll_ifindex as usize 1073 } 1074 1075 /// ARP hardware type hatype(&self) -> u161076 pub fn hatype(&self) -> u16 { 1077 self.0.sll_hatype 1078 } 1079 1080 /// Packet type pkttype(&self) -> u81081 pub fn pkttype(&self) -> u8 { 1082 self.0.sll_pkttype 1083 } 1084 1085 /// Length of MAC address halen(&self) -> usize1086 pub fn halen(&self) -> usize { 1087 self.0.sll_halen as usize 1088 } 1089 1090 /// Physical-layer address (MAC) addr(&self) -> [u8; 6]1091 pub fn addr(&self) -> [u8; 6] { 1092 [ 1093 self.0.sll_addr[0] as u8, 1094 self.0.sll_addr[1] as u8, 1095 self.0.sll_addr[2] as u8, 1096 self.0.sll_addr[3] as u8, 1097 self.0.sll_addr[4] as u8, 1098 self.0.sll_addr[5] as u8, 1099 ] 1100 } 1101 } 1102 1103 impl fmt::Display for LinkAddr { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1104 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1105 let addr = self.addr(); 1106 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", 1107 addr[0], 1108 addr[1], 1109 addr[2], 1110 addr[3], 1111 addr[4], 1112 addr[5]) 1113 } 1114 } 1115 } 1116 1117 #[cfg(any(target_os = "dragonfly", 1118 target_os = "freebsd", 1119 target_os = "ios", 1120 target_os = "macos", 1121 target_os = "netbsd", 1122 target_os = "openbsd"))] 1123 mod datalink { 1124 use super::{fmt, AddressFamily}; 1125 1126 /// Hardware Address 1127 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 1128 pub struct LinkAddr(pub libc::sockaddr_dl); 1129 1130 impl LinkAddr { 1131 /// Total length of sockaddr len(&self) -> usize1132 pub fn len(&self) -> usize { 1133 self.0.sdl_len as usize 1134 } 1135 1136 /// always == AF_LINK family(&self) -> AddressFamily1137 pub fn family(&self) -> AddressFamily { 1138 assert_eq!(i32::from(self.0.sdl_family), libc::AF_LINK); 1139 AddressFamily::Link 1140 } 1141 1142 /// interface index, if != 0, system given index for interface ifindex(&self) -> usize1143 pub fn ifindex(&self) -> usize { 1144 self.0.sdl_index as usize 1145 } 1146 1147 /// Datalink type datalink_type(&self) -> u81148 pub fn datalink_type(&self) -> u8 { 1149 self.0.sdl_type 1150 } 1151 1152 // MAC address start position nlen(&self) -> usize1153 pub fn nlen(&self) -> usize { 1154 self.0.sdl_nlen as usize 1155 } 1156 1157 /// link level address length alen(&self) -> usize1158 pub fn alen(&self) -> usize { 1159 self.0.sdl_alen as usize 1160 } 1161 1162 /// link layer selector length slen(&self) -> usize1163 pub fn slen(&self) -> usize { 1164 self.0.sdl_slen as usize 1165 } 1166 1167 /// if link level address length == 0, 1168 /// or `sdl_data` not be larger. is_empty(&self) -> bool1169 pub fn is_empty(&self) -> bool { 1170 let nlen = self.nlen(); 1171 let alen = self.alen(); 1172 let data_len = self.0.sdl_data.len(); 1173 1174 alen == 0 || nlen + alen >= data_len 1175 } 1176 1177 /// Physical-layer address (MAC) addr(&self) -> [u8; 6]1178 pub fn addr(&self) -> [u8; 6] { 1179 let nlen = self.nlen(); 1180 let data = self.0.sdl_data; 1181 1182 assert!(!self.is_empty()); 1183 1184 [ 1185 data[nlen] as u8, 1186 data[nlen + 1] as u8, 1187 data[nlen + 2] as u8, 1188 data[nlen + 3] as u8, 1189 data[nlen + 4] as u8, 1190 data[nlen + 5] as u8, 1191 ] 1192 } 1193 } 1194 1195 impl fmt::Display for LinkAddr { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1196 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1197 let addr = self.addr(); 1198 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", 1199 addr[0], 1200 addr[1], 1201 addr[2], 1202 addr[3], 1203 addr[4], 1204 addr[5]) 1205 } 1206 } 1207 } 1208 1209 #[cfg(any(target_os = "android", target_os = "linux"))] 1210 pub mod vsock { 1211 use crate::sys::socket::addr::AddressFamily; 1212 use libc::{sa_family_t, sockaddr_vm}; 1213 use std::{fmt, mem}; 1214 use std::hash::{Hash, Hasher}; 1215 1216 #[derive(Copy, Clone)] 1217 pub struct VsockAddr(pub sockaddr_vm); 1218 1219 impl PartialEq for VsockAddr { eq(&self, other: &Self) -> bool1220 fn eq(&self, other: &Self) -> bool { 1221 let (inner, other) = (self.0, other.0); 1222 (inner.svm_family, inner.svm_cid, inner.svm_port) == 1223 (other.svm_family, other.svm_cid, other.svm_port) 1224 } 1225 } 1226 1227 impl Eq for VsockAddr {} 1228 1229 impl Hash for VsockAddr { hash<H: Hasher>(&self, s: &mut H)1230 fn hash<H: Hasher>(&self, s: &mut H) { 1231 let inner = self.0; 1232 (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s); 1233 } 1234 } 1235 1236 /// VSOCK Address 1237 /// 1238 /// The address for AF_VSOCK socket is defined as a combination of a 1239 /// 32-bit Context Identifier (CID) and a 32-bit port number. 1240 impl VsockAddr { new(cid: u32, port: u32) -> VsockAddr1241 pub fn new(cid: u32, port: u32) -> VsockAddr { 1242 let mut addr: sockaddr_vm = unsafe { mem::zeroed() }; 1243 addr.svm_family = AddressFamily::Vsock as sa_family_t; 1244 addr.svm_cid = cid; 1245 addr.svm_port = port; 1246 1247 VsockAddr(addr) 1248 } 1249 1250 /// Context Identifier (CID) cid(&self) -> u321251 pub fn cid(&self) -> u32 { 1252 self.0.svm_cid 1253 } 1254 1255 /// Port number port(&self) -> u321256 pub fn port(&self) -> u32 { 1257 self.0.svm_port 1258 } 1259 } 1260 1261 impl fmt::Display for VsockAddr { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1262 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1263 write!(f, "cid: {} port: {}", self.cid(), self.port()) 1264 } 1265 } 1266 1267 impl fmt::Debug for VsockAddr { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1268 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1269 fmt::Display::fmt(self, f) 1270 } 1271 } 1272 } 1273 1274 #[cfg(test)] 1275 mod tests { 1276 #[cfg(any(target_os = "android", 1277 target_os = "dragonfly", 1278 target_os = "freebsd", 1279 target_os = "ios", 1280 target_os = "linux", 1281 target_os = "macos", 1282 target_os = "netbsd", 1283 target_os = "openbsd"))] 1284 use super::*; 1285 1286 #[cfg(any(target_os = "dragonfly", 1287 target_os = "freebsd", 1288 target_os = "ios", 1289 target_os = "macos", 1290 target_os = "netbsd", 1291 target_os = "openbsd"))] 1292 #[test] test_macos_loopback_datalink_addr()1293 fn test_macos_loopback_datalink_addr() { 1294 let bytes = [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0]; 1295 let sa = bytes.as_ptr() as *const libc::sockaddr; 1296 let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) }; 1297 assert!(_sock_addr.is_none()); 1298 } 1299 1300 #[cfg(any(target_os = "dragonfly", 1301 target_os = "freebsd", 1302 target_os = "ios", 1303 target_os = "macos", 1304 target_os = "netbsd", 1305 target_os = "openbsd"))] 1306 #[test] test_macos_tap_datalink_addr()1307 fn test_macos_tap_datalink_addr() { 1308 let bytes = [20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35, 76, -80]; 1309 let ptr = bytes.as_ptr(); 1310 let sa = ptr as *const libc::sockaddr; 1311 let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) }; 1312 1313 assert!(_sock_addr.is_some()); 1314 1315 let sock_addr = _sock_addr.unwrap(); 1316 1317 assert_eq!(sock_addr.family(), AddressFamily::Link); 1318 1319 match sock_addr { 1320 SockAddr::Link(ether_addr) => { 1321 assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]); 1322 }, 1323 _ => { unreachable!() } 1324 }; 1325 } 1326 1327 #[cfg(any(target_os = "android", target_os = "linux"))] 1328 #[test] test_abstract_sun_path()1329 fn test_abstract_sun_path() { 1330 let name = String::from("nix\0abstract\0test"); 1331 let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap(); 1332 1333 let sun_path1 = addr.sun_path(); 1334 let sun_path2 = [0u8, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116]; 1335 assert_eq!(sun_path1.len(), sun_path2.len()); 1336 for i in 0..sun_path1.len() { 1337 assert_eq!(sun_path1[i], sun_path2[i]); 1338 } 1339 } 1340 } 1341