1#[cfg(any( 2 target_os = "android", 3 target_os = "dragonfly", 4 target_os = "freebsd", 5 target_os = "ios", 6 target_os = "linux", 7 target_os = "macos", 8 target_os = "illumos", 9 target_os = "netbsd", 10 target_os = "openbsd", 11 target_os = "haiku", 12 target_os = "fuchsia" 13))] 14#[cfg(feature = "net")] 15pub use self::datalink::LinkAddr; 16#[cfg(any(target_os = "android", target_os = "linux"))] 17pub use self::vsock::VsockAddr; 18use super::sa_family_t; 19use crate::errno::Errno; 20#[cfg(any(target_os = "android", target_os = "linux"))] 21use crate::sys::socket::addr::alg::AlgAddr; 22#[cfg(any(target_os = "android", target_os = "linux"))] 23use crate::sys::socket::addr::netlink::NetlinkAddr; 24#[cfg(all( 25 feature = "ioctl", 26 any(target_os = "ios", target_os = "macos") 27))] 28use crate::sys::socket::addr::sys_control::SysControlAddr; 29use crate::{NixPath, Result}; 30use cfg_if::cfg_if; 31use memoffset::offset_of; 32use std::convert::TryInto; 33use std::ffi::OsStr; 34use std::hash::{Hash, Hasher}; 35use std::os::unix::ffi::OsStrExt; 36#[cfg(any(target_os = "ios", target_os = "macos"))] 37use std::os::unix::io::RawFd; 38use std::path::Path; 39use std::{fmt, mem, net, ptr, slice}; 40 41/// Convert a std::net::Ipv4Addr into the libc form. 42#[cfg(feature = "net")] 43pub(crate) const fn ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr { 44 static_assertions::assert_eq_size!(net::Ipv4Addr, libc::in_addr); 45 // Safe because both types have the same memory layout, and no fancy Drop 46 // impls. 47 unsafe { 48 mem::transmute(addr) 49 } 50} 51 52/// Convert a std::net::Ipv6Addr into the libc form. 53#[cfg(feature = "net")] 54pub(crate) const fn ipv6addr_to_libc(addr: &net::Ipv6Addr) -> libc::in6_addr { 55 static_assertions::assert_eq_size!(net::Ipv6Addr, libc::in6_addr); 56 // Safe because both are Newtype wrappers around the same libc type 57 unsafe { 58 mem::transmute(*addr) 59 } 60} 61 62/// These constants specify the protocol family to be used 63/// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html) 64/// 65/// # References 66/// 67/// [address_families(7)](https://man7.org/linux/man-pages/man7/address_families.7.html) 68// Should this be u8? 69#[repr(i32)] 70#[non_exhaustive] 71#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] 72pub enum AddressFamily { 73 /// Local communication (see [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html)) 74 Unix = libc::AF_UNIX, 75 /// IPv4 Internet protocols (see [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html)) 76 Inet = libc::AF_INET, 77 /// IPv6 Internet protocols (see [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html)) 78 Inet6 = libc::AF_INET6, 79 /// Kernel user interface device (see [`netlink(7)`](https://man7.org/linux/man-pages/man7/netlink.7.html)) 80 #[cfg(any(target_os = "android", target_os = "linux"))] 81 #[cfg_attr(docsrs, doc(cfg(all())))] 82 Netlink = libc::AF_NETLINK, 83 /// Low level packet interface (see [`packet(7)`](https://man7.org/linux/man-pages/man7/packet.7.html)) 84 #[cfg(any( 85 target_os = "android", 86 target_os = "linux", 87 target_os = "illumos", 88 target_os = "fuchsia", 89 target_os = "solaris" 90 ))] 91 #[cfg_attr(docsrs, doc(cfg(all())))] 92 Packet = libc::AF_PACKET, 93 /// KEXT Controls and Notifications 94 #[cfg(any(target_os = "ios", target_os = "macos"))] 95 #[cfg_attr(docsrs, doc(cfg(all())))] 96 System = libc::AF_SYSTEM, 97 /// Amateur radio AX.25 protocol 98 #[cfg(any(target_os = "android", target_os = "linux"))] 99 #[cfg_attr(docsrs, doc(cfg(all())))] 100 Ax25 = libc::AF_AX25, 101 /// IPX - Novell protocols 102 Ipx = libc::AF_IPX, 103 /// AppleTalk 104 AppleTalk = libc::AF_APPLETALK, 105 /// AX.25 packet layer protocol. 106 /// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/)) 107 #[cfg(any(target_os = "android", target_os = "linux"))] 108 #[cfg_attr(docsrs, doc(cfg(all())))] 109 NetRom = libc::AF_NETROM, 110 /// Can't be used for creating sockets; mostly used for bridge 111 /// links in 112 /// [rtnetlink(7)](https://man7.org/linux/man-pages/man7/rtnetlink.7.html) 113 /// protocol commands. 114 #[cfg(any(target_os = "android", target_os = "linux"))] 115 #[cfg_attr(docsrs, doc(cfg(all())))] 116 Bridge = libc::AF_BRIDGE, 117 /// Access to raw ATM PVCs 118 #[cfg(any(target_os = "android", target_os = "linux"))] 119 #[cfg_attr(docsrs, doc(cfg(all())))] 120 AtmPvc = libc::AF_ATMPVC, 121 /// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](https://man7.org/linux/man-pages/man7/x25.7.html)) 122 #[cfg(any(target_os = "android", target_os = "linux"))] 123 #[cfg_attr(docsrs, doc(cfg(all())))] 124 X25 = libc::AF_X25, 125 /// RATS (Radio Amateur Telecommunications Society) Open 126 /// Systems environment (ROSE) AX.25 packet layer protocol. 127 /// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/)) 128 #[cfg(any(target_os = "android", target_os = "linux"))] 129 #[cfg_attr(docsrs, doc(cfg(all())))] 130 Rose = libc::AF_ROSE, 131 /// DECet protocol sockets. 132 #[cfg(not(target_os = "haiku"))] 133 Decnet = libc::AF_DECnet, 134 /// Reserved for "802.2LLC project"; never used. 135 #[cfg(any(target_os = "android", target_os = "linux"))] 136 #[cfg_attr(docsrs, doc(cfg(all())))] 137 NetBeui = libc::AF_NETBEUI, 138 /// This was a short-lived (between Linux 2.1.30 and 139 /// 2.1.99pre2) protocol family for firewall upcalls. 140 #[cfg(any(target_os = "android", target_os = "linux"))] 141 #[cfg_attr(docsrs, doc(cfg(all())))] 142 Security = libc::AF_SECURITY, 143 /// Key management protocol. 144 #[cfg(any(target_os = "android", target_os = "linux"))] 145 #[cfg_attr(docsrs, doc(cfg(all())))] 146 Key = libc::AF_KEY, 147 #[allow(missing_docs)] // Not documented anywhere that I can find 148 #[cfg(any(target_os = "android", target_os = "linux"))] 149 #[cfg_attr(docsrs, doc(cfg(all())))] 150 Ash = libc::AF_ASH, 151 /// Acorn Econet protocol 152 #[cfg(any(target_os = "android", target_os = "linux"))] 153 #[cfg_attr(docsrs, doc(cfg(all())))] 154 Econet = libc::AF_ECONET, 155 /// Access to ATM Switched Virtual Circuits 156 #[cfg(any(target_os = "android", target_os = "linux"))] 157 #[cfg_attr(docsrs, doc(cfg(all())))] 158 AtmSvc = libc::AF_ATMSVC, 159 /// Reliable Datagram Sockets (RDS) protocol 160 #[cfg(any(target_os = "android", target_os = "linux"))] 161 #[cfg_attr(docsrs, doc(cfg(all())))] 162 Rds = libc::AF_RDS, 163 /// IBM SNA 164 #[cfg(not(target_os = "haiku"))] 165 Sna = libc::AF_SNA, 166 /// Socket interface over IrDA 167 #[cfg(any(target_os = "android", target_os = "linux"))] 168 #[cfg_attr(docsrs, doc(cfg(all())))] 169 Irda = libc::AF_IRDA, 170 /// Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE) 171 #[cfg(any(target_os = "android", target_os = "linux"))] 172 #[cfg_attr(docsrs, doc(cfg(all())))] 173 Pppox = libc::AF_PPPOX, 174 /// Legacy protocol for wide area network (WAN) connectivity that was used 175 /// by Sangoma WAN cards 176 #[cfg(any(target_os = "android", target_os = "linux"))] 177 #[cfg_attr(docsrs, doc(cfg(all())))] 178 Wanpipe = libc::AF_WANPIPE, 179 /// Logical link control (IEEE 802.2 LLC) protocol 180 #[cfg(any(target_os = "android", target_os = "linux"))] 181 #[cfg_attr(docsrs, doc(cfg(all())))] 182 Llc = libc::AF_LLC, 183 /// InfiniBand native addressing 184 #[cfg(all(target_os = "linux", not(target_env = "uclibc")))] 185 #[cfg_attr(docsrs, doc(cfg(all())))] 186 Ib = libc::AF_IB, 187 /// Multiprotocol Label Switching 188 #[cfg(all(target_os = "linux", not(target_env = "uclibc")))] 189 #[cfg_attr(docsrs, doc(cfg(all())))] 190 Mpls = libc::AF_MPLS, 191 /// Controller Area Network automotive bus protocol 192 #[cfg(any(target_os = "android", target_os = "linux"))] 193 #[cfg_attr(docsrs, doc(cfg(all())))] 194 Can = libc::AF_CAN, 195 /// TIPC, "cluster domain sockets" protocol 196 #[cfg(any(target_os = "android", target_os = "linux"))] 197 #[cfg_attr(docsrs, doc(cfg(all())))] 198 Tipc = libc::AF_TIPC, 199 /// Bluetooth low-level socket protocol 200 #[cfg(not(any( 201 target_os = "illumos", 202 target_os = "ios", 203 target_os = "macos", 204 target_os = "solaris" 205 )))] 206 #[cfg_attr(docsrs, doc(cfg(all())))] 207 Bluetooth = libc::AF_BLUETOOTH, 208 /// IUCV (inter-user communication vehicle) z/VM protocol for 209 /// hypervisor-guest interaction 210 #[cfg(any(target_os = "android", target_os = "linux"))] 211 #[cfg_attr(docsrs, doc(cfg(all())))] 212 Iucv = libc::AF_IUCV, 213 /// Rx, Andrew File System remote procedure call protocol 214 #[cfg(any(target_os = "android", target_os = "linux"))] 215 #[cfg_attr(docsrs, doc(cfg(all())))] 216 RxRpc = libc::AF_RXRPC, 217 /// New "modular ISDN" driver interface protocol 218 #[cfg(not(any( 219 target_os = "illumos", 220 target_os = "solaris", 221 target_os = "haiku" 222 )))] 223 #[cfg_attr(docsrs, doc(cfg(all())))] 224 Isdn = libc::AF_ISDN, 225 /// Nokia cellular modem IPC/RPC interface 226 #[cfg(any(target_os = "android", target_os = "linux"))] 227 #[cfg_attr(docsrs, doc(cfg(all())))] 228 Phonet = libc::AF_PHONET, 229 /// IEEE 802.15.4 WPAN (wireless personal area network) raw packet protocol 230 #[cfg(any(target_os = "android", target_os = "linux"))] 231 #[cfg_attr(docsrs, doc(cfg(all())))] 232 Ieee802154 = libc::AF_IEEE802154, 233 /// Ericsson's Communication CPU to Application CPU interface (CAIF) 234 /// protocol. 235 #[cfg(any(target_os = "android", target_os = "linux"))] 236 #[cfg_attr(docsrs, doc(cfg(all())))] 237 Caif = libc::AF_CAIF, 238 /// Interface to kernel crypto API 239 #[cfg(any(target_os = "android", target_os = "linux"))] 240 #[cfg_attr(docsrs, doc(cfg(all())))] 241 Alg = libc::AF_ALG, 242 /// Near field communication 243 #[cfg(target_os = "linux")] 244 #[cfg_attr(docsrs, doc(cfg(all())))] 245 Nfc = libc::AF_NFC, 246 /// VMWare VSockets protocol for hypervisor-guest interaction. 247 #[cfg(any(target_os = "android", target_os = "linux"))] 248 #[cfg_attr(docsrs, doc(cfg(all())))] 249 Vsock = libc::AF_VSOCK, 250 /// ARPANet IMP addresses 251 #[cfg(any( 252 target_os = "dragonfly", 253 target_os = "freebsd", 254 target_os = "ios", 255 target_os = "macos", 256 target_os = "netbsd", 257 target_os = "openbsd" 258 ))] 259 #[cfg_attr(docsrs, doc(cfg(all())))] 260 ImpLink = libc::AF_IMPLINK, 261 /// PUP protocols, e.g. BSP 262 #[cfg(any( 263 target_os = "dragonfly", 264 target_os = "freebsd", 265 target_os = "ios", 266 target_os = "macos", 267 target_os = "netbsd", 268 target_os = "openbsd" 269 ))] 270 #[cfg_attr(docsrs, doc(cfg(all())))] 271 Pup = libc::AF_PUP, 272 /// MIT CHAOS protocols 273 #[cfg(any( 274 target_os = "dragonfly", 275 target_os = "freebsd", 276 target_os = "ios", 277 target_os = "macos", 278 target_os = "netbsd", 279 target_os = "openbsd" 280 ))] 281 #[cfg_attr(docsrs, doc(cfg(all())))] 282 Chaos = libc::AF_CHAOS, 283 /// Novell and Xerox protocol 284 #[cfg(any( 285 target_os = "ios", 286 target_os = "macos", 287 target_os = "netbsd", 288 target_os = "openbsd" 289 ))] 290 #[cfg_attr(docsrs, doc(cfg(all())))] 291 Ns = libc::AF_NS, 292 #[allow(missing_docs)] // Not documented anywhere that I can find 293 #[cfg(any( 294 target_os = "dragonfly", 295 target_os = "freebsd", 296 target_os = "ios", 297 target_os = "macos", 298 target_os = "netbsd", 299 target_os = "openbsd" 300 ))] 301 #[cfg_attr(docsrs, doc(cfg(all())))] 302 Iso = libc::AF_ISO, 303 /// Bell Labs virtual circuit switch ? 304 #[cfg(any( 305 target_os = "dragonfly", 306 target_os = "freebsd", 307 target_os = "ios", 308 target_os = "macos", 309 target_os = "netbsd", 310 target_os = "openbsd" 311 ))] 312 #[cfg_attr(docsrs, doc(cfg(all())))] 313 Datakit = libc::AF_DATAKIT, 314 /// CCITT protocols, X.25 etc 315 #[cfg(any( 316 target_os = "dragonfly", 317 target_os = "freebsd", 318 target_os = "ios", 319 target_os = "macos", 320 target_os = "netbsd", 321 target_os = "openbsd" 322 ))] 323 #[cfg_attr(docsrs, doc(cfg(all())))] 324 Ccitt = libc::AF_CCITT, 325 /// DEC Direct data link interface 326 #[cfg(any( 327 target_os = "dragonfly", 328 target_os = "freebsd", 329 target_os = "ios", 330 target_os = "macos", 331 target_os = "netbsd", 332 target_os = "openbsd" 333 ))] 334 #[cfg_attr(docsrs, doc(cfg(all())))] 335 Dli = libc::AF_DLI, 336 #[allow(missing_docs)] // Not documented anywhere that I can find 337 #[cfg(any( 338 target_os = "dragonfly", 339 target_os = "freebsd", 340 target_os = "ios", 341 target_os = "macos", 342 target_os = "netbsd", 343 target_os = "openbsd" 344 ))] 345 #[cfg_attr(docsrs, doc(cfg(all())))] 346 Lat = libc::AF_LAT, 347 /// NSC Hyperchannel 348 #[cfg(any( 349 target_os = "dragonfly", 350 target_os = "freebsd", 351 target_os = "ios", 352 target_os = "macos", 353 target_os = "netbsd", 354 target_os = "openbsd" 355 ))] 356 #[cfg_attr(docsrs, doc(cfg(all())))] 357 Hylink = libc::AF_HYLINK, 358 /// Link layer interface 359 #[cfg(any( 360 target_os = "dragonfly", 361 target_os = "freebsd", 362 target_os = "ios", 363 target_os = "macos", 364 target_os = "illumos", 365 target_os = "netbsd", 366 target_os = "openbsd" 367 ))] 368 #[cfg_attr(docsrs, doc(cfg(all())))] 369 Link = libc::AF_LINK, 370 /// connection-oriented IP, aka ST II 371 #[cfg(any( 372 target_os = "dragonfly", 373 target_os = "freebsd", 374 target_os = "ios", 375 target_os = "macos", 376 target_os = "netbsd", 377 target_os = "openbsd" 378 ))] 379 #[cfg_attr(docsrs, doc(cfg(all())))] 380 Coip = libc::AF_COIP, 381 /// Computer Network Technology 382 #[cfg(any( 383 target_os = "dragonfly", 384 target_os = "freebsd", 385 target_os = "ios", 386 target_os = "macos", 387 target_os = "netbsd", 388 target_os = "openbsd" 389 ))] 390 #[cfg_attr(docsrs, doc(cfg(all())))] 391 Cnt = libc::AF_CNT, 392 /// Native ATM access 393 #[cfg(any( 394 target_os = "dragonfly", 395 target_os = "freebsd", 396 target_os = "ios", 397 target_os = "macos", 398 target_os = "netbsd", 399 target_os = "openbsd" 400 ))] 401 #[cfg_attr(docsrs, doc(cfg(all())))] 402 Natm = libc::AF_NATM, 403 /// Unspecified address family, (see [`getaddrinfo(3)`](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html)) 404 #[cfg(any(target_os = "android", target_os = "linux"))] 405 #[cfg_attr(docsrs, doc(cfg(all())))] 406 Unspec = libc::AF_UNSPEC, 407} 408 409impl AddressFamily { 410 /// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from 411 /// the `sa_family` field of a `sockaddr`. 412 /// 413 /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet 414 /// and System. Returns None for unsupported or unknown address families. 415 pub const fn from_i32(family: i32) -> Option<AddressFamily> { 416 match family { 417 libc::AF_UNIX => Some(AddressFamily::Unix), 418 libc::AF_INET => Some(AddressFamily::Inet), 419 libc::AF_INET6 => Some(AddressFamily::Inet6), 420 #[cfg(any(target_os = "android", target_os = "linux"))] 421 libc::AF_NETLINK => Some(AddressFamily::Netlink), 422 #[cfg(any(target_os = "macos", target_os = "macos"))] 423 libc::AF_SYSTEM => Some(AddressFamily::System), 424 #[cfg(any(target_os = "android", target_os = "linux"))] 425 libc::AF_PACKET => Some(AddressFamily::Packet), 426 #[cfg(any( 427 target_os = "dragonfly", 428 target_os = "freebsd", 429 target_os = "ios", 430 target_os = "macos", 431 target_os = "netbsd", 432 target_os = "illumos", 433 target_os = "openbsd" 434 ))] 435 libc::AF_LINK => Some(AddressFamily::Link), 436 #[cfg(any(target_os = "android", target_os = "linux"))] 437 libc::AF_VSOCK => Some(AddressFamily::Vsock), 438 _ => None, 439 } 440 } 441} 442 443feature! { 444#![feature = "net"] 445 446#[deprecated( 447 since = "0.24.0", 448 note = "use SockaddrIn, SockaddrIn6, or SockaddrStorage instead" 449)] 450#[allow(missing_docs)] // Since they're all deprecated anyway 451#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 452pub enum InetAddr { 453 V4(libc::sockaddr_in), 454 V6(libc::sockaddr_in6), 455} 456 457#[allow(missing_docs)] // It's deprecated anyway 458#[allow(deprecated)] 459impl InetAddr { 460 #[allow(clippy::needless_update)] // It isn't needless on all OSes 461 pub fn from_std(std: &net::SocketAddr) -> InetAddr { 462 match *std { 463 net::SocketAddr::V4(ref addr) => { 464 InetAddr::V4(libc::sockaddr_in { 465 #[cfg(any(target_os = "dragonfly", target_os = "freebsd", 466 target_os = "haiku", target_os = "hermit", 467 target_os = "ios", target_os = "macos", 468 target_os = "netbsd", target_os = "openbsd"))] 469 sin_len: mem::size_of::<libc::sockaddr_in>() as u8, 470 sin_family: AddressFamily::Inet as sa_family_t, 471 sin_port: addr.port().to_be(), // network byte order 472 sin_addr: Ipv4Addr::from_std(addr.ip()).0, 473 .. unsafe { mem::zeroed() } 474 }) 475 } 476 net::SocketAddr::V6(ref addr) => { 477 InetAddr::V6(libc::sockaddr_in6 { 478 #[cfg(any(target_os = "dragonfly", target_os = "freebsd", 479 target_os = "haiku", target_os = "hermit", 480 target_os = "ios", target_os = "macos", 481 target_os = "netbsd", target_os = "openbsd"))] 482 sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8, 483 sin6_family: AddressFamily::Inet6 as sa_family_t, 484 sin6_port: addr.port().to_be(), // network byte order 485 sin6_addr: Ipv6Addr::from_std(addr.ip()).0, 486 sin6_flowinfo: addr.flowinfo(), // host byte order 487 sin6_scope_id: addr.scope_id(), // host byte order 488 .. unsafe { mem::zeroed() } 489 }) 490 } 491 } 492 } 493 494 #[allow(clippy::needless_update)] // It isn't needless on all OSes 495 pub fn new(ip: IpAddr, port: u16) -> InetAddr { 496 match ip { 497 IpAddr::V4(ref ip) => { 498 InetAddr::V4(libc::sockaddr_in { 499 sin_family: AddressFamily::Inet as sa_family_t, 500 sin_port: port.to_be(), 501 sin_addr: ip.0, 502 .. unsafe { mem::zeroed() } 503 }) 504 } 505 IpAddr::V6(ref ip) => { 506 InetAddr::V6(libc::sockaddr_in6 { 507 sin6_family: AddressFamily::Inet6 as sa_family_t, 508 sin6_port: port.to_be(), 509 sin6_addr: ip.0, 510 .. unsafe { mem::zeroed() } 511 }) 512 } 513 } 514 } 515 /// Gets the IP address associated with this socket address. 516 pub const fn ip(&self) -> IpAddr { 517 match *self { 518 InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)), 519 InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)), 520 } 521 } 522 523 /// Gets the port number associated with this socket address 524 pub const fn port(&self) -> u16 { 525 match *self { 526 InetAddr::V6(ref sa) => u16::from_be(sa.sin6_port), 527 InetAddr::V4(ref sa) => u16::from_be(sa.sin_port), 528 } 529 } 530 531 pub fn to_std(&self) -> net::SocketAddr { 532 match *self { 533 InetAddr::V4(ref sa) => net::SocketAddr::V4( 534 net::SocketAddrV4::new( 535 Ipv4Addr(sa.sin_addr).to_std(), 536 self.port())), 537 InetAddr::V6(ref sa) => net::SocketAddr::V6( 538 net::SocketAddrV6::new( 539 Ipv6Addr(sa.sin6_addr).to_std(), 540 self.port(), 541 sa.sin6_flowinfo, 542 sa.sin6_scope_id)), 543 } 544 } 545 546 #[deprecated(since = "0.23.0", note = "use .to_string() instead")] 547 pub fn to_str(&self) -> String { 548 format!("{}", self) 549 } 550} 551 552#[allow(deprecated)] 553impl fmt::Display for InetAddr { 554 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 555 match *self { 556 InetAddr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()), 557 InetAddr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()), 558 } 559 } 560} 561 562/* 563 * 564 * ===== IpAddr ===== 565 * 566 */ 567#[allow(missing_docs)] // Since they're all deprecated anyway 568#[allow(deprecated)] 569#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 570#[deprecated( 571 since = "0.24.0", 572 note = "Use std::net::IpAddr instead" 573)] 574pub enum IpAddr { 575 V4(Ipv4Addr), 576 V6(Ipv6Addr), 577} 578 579#[allow(deprecated)] 580#[allow(missing_docs)] // Since they're all deprecated anyway 581impl IpAddr { 582 /// Create a new IpAddr that contains an IPv4 address. 583 /// 584 /// The result will represent the IP address a.b.c.d 585 pub const fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr { 586 IpAddr::V4(Ipv4Addr::new(a, b, c, d)) 587 } 588 589 /// Create a new IpAddr that contains an IPv6 address. 590 /// 591 /// The result will represent the IP address a:b:c:d:e:f 592 #[allow(clippy::many_single_char_names)] 593 #[allow(clippy::too_many_arguments)] 594 pub const fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr { 595 IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h)) 596 } 597 598 pub fn from_std(std: &net::IpAddr) -> IpAddr { 599 match *std { 600 net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)), 601 net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)), 602 } 603 } 604 605 pub const fn to_std(&self) -> net::IpAddr { 606 match *self { 607 IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()), 608 IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()), 609 } 610 } 611} 612 613#[allow(deprecated)] 614impl fmt::Display for IpAddr { 615 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 616 match *self { 617 IpAddr::V4(ref v4) => v4.fmt(f), 618 IpAddr::V6(ref v6) => v6.fmt(f) 619 } 620 } 621} 622 623/* 624 * 625 * ===== Ipv4Addr ===== 626 * 627 */ 628 629#[deprecated( 630 since = "0.24.0", 631 note = "Use std::net::Ipv4Addr instead" 632)] 633#[allow(missing_docs)] // Since they're all deprecated anyway 634#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 635#[repr(transparent)] 636pub struct Ipv4Addr(pub libc::in_addr); 637 638#[allow(deprecated)] 639#[allow(missing_docs)] // Since they're all deprecated anyway 640impl Ipv4Addr { 641 #[allow(clippy::identity_op)] // More readable this way 642 pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { 643 let ip = (((a as u32) << 24) | 644 ((b as u32) << 16) | 645 ((c as u32) << 8) | 646 ((d as u32) << 0)).to_be(); 647 648 Ipv4Addr(libc::in_addr { s_addr: ip }) 649 } 650 651 // Use pass by reference for symmetry with Ipv6Addr::from_std 652 #[allow(clippy::trivially_copy_pass_by_ref)] 653 pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr { 654 let bits = std.octets(); 655 Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3]) 656 } 657 658 pub const fn any() -> Ipv4Addr { 659 Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY }) 660 } 661 662 pub const fn octets(self) -> [u8; 4] { 663 let bits = u32::from_be(self.0.s_addr); 664 [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8] 665 } 666 667 pub const fn to_std(self) -> net::Ipv4Addr { 668 let bits = self.octets(); 669 net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3]) 670 } 671} 672 673#[allow(deprecated)] 674impl fmt::Display for Ipv4Addr { 675 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 676 let octets = self.octets(); 677 write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]) 678 } 679} 680 681/* 682 * 683 * ===== Ipv6Addr ===== 684 * 685 */ 686 687#[deprecated( 688 since = "0.24.0", 689 note = "Use std::net::Ipv6Addr instead" 690)] 691#[allow(missing_docs)] // Since they're all deprecated anyway 692#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 693#[repr(transparent)] 694pub struct Ipv6Addr(pub libc::in6_addr); 695 696// Note that IPv6 addresses are stored in big endian order on all architectures. 697// See https://tools.ietf.org/html/rfc1700 or consult your favorite search 698// engine. 699 700macro_rules! to_u8_array { 701 ($($num:ident),*) => { 702 [ $(($num>>8) as u8, ($num&0xff) as u8,)* ] 703 } 704} 705 706macro_rules! to_u16_array { 707 ($slf:ident, $($first:expr, $second:expr),*) => { 708 [$( (($slf.0.s6_addr[$first] as u16) << 8) + $slf.0.s6_addr[$second] as u16,)*] 709 } 710} 711 712#[allow(deprecated)] 713#[allow(missing_docs)] // Since they're all deprecated anyway 714impl Ipv6Addr { 715 #[allow(clippy::many_single_char_names)] 716 #[allow(clippy::too_many_arguments)] 717 pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { 718 Ipv6Addr(libc::in6_addr{s6_addr: to_u8_array!(a,b,c,d,e,f,g,h)}) 719 } 720 721 pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr { 722 let s = std.segments(); 723 Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]) 724 } 725 726 /// Return the eight 16-bit segments that make up this address 727 pub const fn segments(&self) -> [u16; 8] { 728 to_u16_array!(self, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15) 729 } 730 731 pub const fn to_std(&self) -> net::Ipv6Addr { 732 let s = self.segments(); 733 net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]) 734 } 735} 736 737#[allow(deprecated)] 738impl fmt::Display for Ipv6Addr { 739 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 740 self.to_std().fmt(fmt) 741 } 742} 743} 744 745/// A wrapper around `sockaddr_un`. 746#[derive(Clone, Copy, Debug)] 747#[repr(C)] 748pub struct UnixAddr { 749 // INVARIANT: sun & sun_len are valid as defined by docs for from_raw_parts 750 sun: libc::sockaddr_un, 751 /// The length of the valid part of `sun`, including the sun_family field 752 /// but excluding any trailing nul. 753 // On the BSDs, this field is built into sun 754 #[cfg(any( 755 target_os = "android", 756 target_os = "fuchsia", 757 target_os = "illumos", 758 target_os = "linux" 759 ))] 760 sun_len: u8, 761} 762 763// linux man page unix(7) says there are 3 kinds of unix socket: 764// pathname: addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1 765// unnamed: addrlen = sizeof(sa_family_t) 766// abstract: addren > sizeof(sa_family_t), name = sun_path[..(addrlen - sizeof(sa_family_t))] 767// 768// what we call path_len = addrlen - offsetof(struct sockaddr_un, sun_path) 769#[derive(PartialEq, Eq, Hash)] 770enum UnixAddrKind<'a> { 771 Pathname(&'a Path), 772 Unnamed, 773 #[cfg(any(target_os = "android", target_os = "linux"))] 774 Abstract(&'a [u8]), 775} 776impl<'a> UnixAddrKind<'a> { 777 /// Safety: sun & sun_len must be valid 778 unsafe fn get(sun: &'a libc::sockaddr_un, sun_len: u8) -> Self { 779 assert!(sun_len as usize >= offset_of!(libc::sockaddr_un, sun_path)); 780 let path_len = 781 sun_len as usize - offset_of!(libc::sockaddr_un, sun_path); 782 if path_len == 0 { 783 return Self::Unnamed; 784 } 785 #[cfg(any(target_os = "android", target_os = "linux"))] 786 if sun.sun_path[0] == 0 { 787 let name = slice::from_raw_parts( 788 sun.sun_path.as_ptr().add(1) as *const u8, 789 path_len - 1, 790 ); 791 return Self::Abstract(name); 792 } 793 let pathname = 794 slice::from_raw_parts(sun.sun_path.as_ptr() as *const u8, path_len); 795 if pathname.last() == Some(&0) { 796 // A trailing NUL is not considered part of the path, and it does 797 // not need to be included in the addrlen passed to functions like 798 // bind(). However, Linux adds a trailing NUL, even if one was not 799 // originally present, when returning addrs from functions like 800 // getsockname() (the BSDs do not do that). So we need to filter 801 // out any trailing NUL here, so sockaddrs can round-trip through 802 // the kernel and still compare equal. 803 Self::Pathname(Path::new(OsStr::from_bytes( 804 &pathname[0..pathname.len() - 1], 805 ))) 806 } else { 807 Self::Pathname(Path::new(OsStr::from_bytes(pathname))) 808 } 809 } 810} 811 812impl UnixAddr { 813 /// Create a new sockaddr_un representing a filesystem path. 814 pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> { 815 path.with_nix_path(|cstr| unsafe { 816 let mut ret = libc::sockaddr_un { 817 sun_family: AddressFamily::Unix as sa_family_t, 818 ..mem::zeroed() 819 }; 820 821 let bytes = cstr.to_bytes(); 822 823 if bytes.len() >= ret.sun_path.len() { 824 return Err(Errno::ENAMETOOLONG); 825 } 826 827 let sun_len = (bytes.len() 828 + offset_of!(libc::sockaddr_un, sun_path)) 829 .try_into() 830 .unwrap(); 831 832 #[cfg(any( 833 target_os = "dragonfly", 834 target_os = "freebsd", 835 target_os = "ios", 836 target_os = "macos", 837 target_os = "netbsd", 838 target_os = "openbsd" 839 ))] 840 { 841 ret.sun_len = sun_len; 842 } 843 ptr::copy_nonoverlapping( 844 bytes.as_ptr(), 845 ret.sun_path.as_mut_ptr() as *mut u8, 846 bytes.len(), 847 ); 848 849 Ok(UnixAddr::from_raw_parts(ret, sun_len)) 850 })? 851 } 852 853 /// Create a new `sockaddr_un` representing an address in the "abstract namespace". 854 /// 855 /// The leading nul byte for the abstract namespace is automatically added; 856 /// thus the input `path` is expected to be the bare name, not NUL-prefixed. 857 /// This is a Linux-specific extension, primarily used to allow chrooted 858 /// processes to communicate with processes having a different filesystem view. 859 #[cfg(any(target_os = "android", target_os = "linux"))] 860 #[cfg_attr(docsrs, doc(cfg(all())))] 861 pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> { 862 unsafe { 863 let mut ret = libc::sockaddr_un { 864 sun_family: AddressFamily::Unix as sa_family_t, 865 ..mem::zeroed() 866 }; 867 868 if path.len() >= ret.sun_path.len() { 869 return Err(Errno::ENAMETOOLONG); 870 } 871 let sun_len = 872 (path.len() + 1 + offset_of!(libc::sockaddr_un, sun_path)) 873 .try_into() 874 .unwrap(); 875 876 // Abstract addresses are represented by sun_path[0] == 877 // b'\0', so copy starting one byte in. 878 ptr::copy_nonoverlapping( 879 path.as_ptr(), 880 ret.sun_path.as_mut_ptr().offset(1) as *mut u8, 881 path.len(), 882 ); 883 884 Ok(UnixAddr::from_raw_parts(ret, sun_len)) 885 } 886 } 887 888 /// Create a new `sockaddr_un` representing an "unnamed" unix socket address. 889 #[cfg(any(target_os = "android", target_os = "linux"))] 890 #[cfg_attr(docsrs, doc(cfg(all())))] 891 pub fn new_unnamed() -> UnixAddr { 892 let ret = libc::sockaddr_un { 893 sun_family: AddressFamily::Unix as sa_family_t, 894 .. unsafe { mem::zeroed() } 895 }; 896 897 let sun_len: u8 = offset_of!(libc::sockaddr_un, sun_path).try_into().unwrap(); 898 899 unsafe { UnixAddr::from_raw_parts(ret, sun_len) } 900 } 901 902 /// Create a UnixAddr from a raw `sockaddr_un` struct and a size. `sun_len` 903 /// is the size of the valid portion of the struct, excluding any trailing 904 /// NUL. 905 /// 906 /// # Safety 907 /// This pair of sockaddr_un & sun_len must be a valid unix addr, which 908 /// means: 909 /// - sun_len >= offset_of(sockaddr_un, sun_path) 910 /// - sun_len <= sockaddr_un.sun_path.len() - offset_of(sockaddr_un, sun_path) 911 /// - if this is a unix addr with a pathname, sun.sun_path is a 912 /// fs path, not necessarily nul-terminated. 913 pub(crate) unsafe fn from_raw_parts( 914 sun: libc::sockaddr_un, 915 sun_len: u8, 916 ) -> UnixAddr { 917 cfg_if! { 918 if #[cfg(any(target_os = "android", 919 target_os = "fuchsia", 920 target_os = "illumos", 921 target_os = "linux" 922 ))] 923 { 924 UnixAddr { sun, sun_len } 925 } else { 926 assert_eq!(sun_len, sun.sun_len); 927 UnixAddr {sun} 928 } 929 } 930 } 931 932 fn kind(&self) -> UnixAddrKind<'_> { 933 // SAFETY: our sockaddr is always valid because of the invariant on the struct 934 unsafe { UnixAddrKind::get(&self.sun, self.sun_len()) } 935 } 936 937 /// If this address represents a filesystem path, return that path. 938 pub fn path(&self) -> Option<&Path> { 939 match self.kind() { 940 UnixAddrKind::Pathname(path) => Some(path), 941 _ => None, 942 } 943 } 944 945 /// If this address represents an abstract socket, return its name. 946 /// 947 /// For abstract sockets only the bare name is returned, without the 948 /// leading NUL byte. `None` is returned for unnamed or path-backed sockets. 949 #[cfg(any(target_os = "android", target_os = "linux"))] 950 #[cfg_attr(docsrs, doc(cfg(all())))] 951 pub fn as_abstract(&self) -> Option<&[u8]> { 952 match self.kind() { 953 UnixAddrKind::Abstract(name) => Some(name), 954 _ => None, 955 } 956 } 957 958 /// Check if this address is an "unnamed" unix socket address. 959 #[cfg(any(target_os = "android", target_os = "linux"))] 960 #[cfg_attr(docsrs, doc(cfg(all())))] 961 #[inline] 962 pub fn is_unnamed(&self) -> bool { 963 matches!(self.kind(), UnixAddrKind::Unnamed) 964 } 965 966 /// Returns the addrlen of this socket - `offsetof(struct sockaddr_un, sun_path)` 967 #[inline] 968 pub fn path_len(&self) -> usize { 969 self.sun_len() as usize - offset_of!(libc::sockaddr_un, sun_path) 970 } 971 /// Returns a pointer to the raw `sockaddr_un` struct 972 #[inline] 973 pub fn as_ptr(&self) -> *const libc::sockaddr_un { 974 &self.sun 975 } 976 /// Returns a mutable pointer to the raw `sockaddr_un` struct 977 #[inline] 978 pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr_un { 979 &mut self.sun 980 } 981 982 fn sun_len(&self) -> u8 { 983 cfg_if! { 984 if #[cfg(any(target_os = "android", 985 target_os = "fuchsia", 986 target_os = "illumos", 987 target_os = "linux" 988 ))] 989 { 990 self.sun_len 991 } else { 992 self.sun.sun_len 993 } 994 } 995 } 996} 997 998impl private::SockaddrLikePriv for UnixAddr {} 999impl SockaddrLike for UnixAddr { 1000 #[cfg(any( 1001 target_os = "android", 1002 target_os = "fuchsia", 1003 target_os = "illumos", 1004 target_os = "linux" 1005 ))] 1006 fn len(&self) -> libc::socklen_t { 1007 self.sun_len.into() 1008 } 1009 1010 unsafe fn from_raw( 1011 addr: *const libc::sockaddr, 1012 len: Option<libc::socklen_t>, 1013 ) -> Option<Self> 1014 where 1015 Self: Sized, 1016 { 1017 if let Some(l) = len { 1018 if (l as usize) < offset_of!(libc::sockaddr_un, sun_path) 1019 || l > u8::MAX as libc::socklen_t 1020 { 1021 return None; 1022 } 1023 } 1024 if (*addr).sa_family as i32 != libc::AF_UNIX { 1025 return None; 1026 } 1027 let mut su: libc::sockaddr_un = mem::zeroed(); 1028 let sup = &mut su as *mut libc::sockaddr_un as *mut u8; 1029 cfg_if! { 1030 if #[cfg(any(target_os = "android", 1031 target_os = "fuchsia", 1032 target_os = "illumos", 1033 target_os = "linux" 1034 ))] { 1035 let su_len = len.unwrap_or( 1036 mem::size_of::<libc::sockaddr_un>() as libc::socklen_t 1037 ); 1038 } else { 1039 let su_len = len.unwrap_or((*addr).sa_len as libc::socklen_t); 1040 } 1041 }; 1042 ptr::copy(addr as *const u8, sup, su_len as usize); 1043 Some(Self::from_raw_parts(su, su_len as u8)) 1044 } 1045 1046 fn size() -> libc::socklen_t 1047 where 1048 Self: Sized, 1049 { 1050 mem::size_of::<libc::sockaddr_un>() as libc::socklen_t 1051 } 1052} 1053 1054impl AsRef<libc::sockaddr_un> for UnixAddr { 1055 fn as_ref(&self) -> &libc::sockaddr_un { 1056 &self.sun 1057 } 1058} 1059 1060#[cfg(any(target_os = "android", target_os = "linux"))] 1061fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result { 1062 use fmt::Write; 1063 f.write_str("@\"")?; 1064 for &b in abs { 1065 use fmt::Display; 1066 char::from(b).escape_default().fmt(f)?; 1067 } 1068 f.write_char('"')?; 1069 Ok(()) 1070} 1071 1072impl fmt::Display for UnixAddr { 1073 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1074 match self.kind() { 1075 UnixAddrKind::Pathname(path) => path.display().fmt(f), 1076 UnixAddrKind::Unnamed => f.pad("<unbound UNIX socket>"), 1077 #[cfg(any(target_os = "android", target_os = "linux"))] 1078 UnixAddrKind::Abstract(name) => fmt_abstract(name, f), 1079 } 1080 } 1081} 1082 1083impl PartialEq for UnixAddr { 1084 fn eq(&self, other: &UnixAddr) -> bool { 1085 self.kind() == other.kind() 1086 } 1087} 1088 1089impl Eq for UnixAddr {} 1090 1091impl Hash for UnixAddr { 1092 fn hash<H: Hasher>(&self, s: &mut H) { 1093 self.kind().hash(s) 1094 } 1095} 1096 1097/// Anything that, in C, can be cast back and forth to `sockaddr`. 1098/// 1099/// Most implementors also implement `AsRef<libc::XXX>` to access their 1100/// inner type read-only. 1101#[allow(clippy::len_without_is_empty)] 1102pub trait SockaddrLike: private::SockaddrLikePriv { 1103 /// Returns a raw pointer to the inner structure. Useful for FFI. 1104 fn as_ptr(&self) -> *const libc::sockaddr { 1105 self as *const Self as *const libc::sockaddr 1106 } 1107 1108 /// Unsafe constructor from a variable length source 1109 /// 1110 /// Some C APIs from provide `len`, and others do not. If it's provided it 1111 /// will be validated. If not, it will be guessed based on the family. 1112 /// 1113 /// # Arguments 1114 /// 1115 /// - `addr`: raw pointer to something that can be cast to a 1116 /// `libc::sockaddr`. For example, `libc::sockaddr_in`, 1117 /// `libc::sockaddr_in6`, etc. 1118 /// - `len`: For fixed-width types like `sockaddr_in`, it will be 1119 /// validated if present and ignored if not. For variable-width 1120 /// types it is required and must be the total length of valid 1121 /// data. For example, if `addr` points to a 1122 /// named `sockaddr_un`, then `len` must be the length of the 1123 /// structure up to but not including the trailing NUL. 1124 /// 1125 /// # Safety 1126 /// 1127 /// `addr` must be valid for the specific type of sockaddr. `len`, if 1128 /// present, must not exceed the length of valid data in `addr`. 1129 unsafe fn from_raw( 1130 addr: *const libc::sockaddr, 1131 len: Option<libc::socklen_t>, 1132 ) -> Option<Self> 1133 where 1134 Self: Sized; 1135 1136 /// Return the address family of this socket 1137 /// 1138 /// # Examples 1139 /// One common use is to match on the family of a union type, like this: 1140 /// ``` 1141 /// # use nix::sys::socket::*; 1142 /// let fd = socket(AddressFamily::Inet, SockType::Stream, 1143 /// SockFlag::empty(), None).unwrap(); 1144 /// let ss: SockaddrStorage = getsockname(fd).unwrap(); 1145 /// match ss.family().unwrap() { 1146 /// AddressFamily::Inet => println!("{}", ss.as_sockaddr_in().unwrap()), 1147 /// AddressFamily::Inet6 => println!("{}", ss.as_sockaddr_in6().unwrap()), 1148 /// _ => println!("Unexpected address family") 1149 /// } 1150 /// ``` 1151 fn family(&self) -> Option<AddressFamily> { 1152 // Safe since all implementors have a sa_family field at the same 1153 // address, and they're all repr(C) 1154 AddressFamily::from_i32(unsafe { 1155 (*(self as *const Self as *const libc::sockaddr)).sa_family as i32 1156 }) 1157 } 1158 1159 cfg_if! { 1160 if #[cfg(any(target_os = "dragonfly", 1161 target_os = "freebsd", 1162 target_os = "ios", 1163 target_os = "macos", 1164 target_os = "netbsd", 1165 target_os = "openbsd"))] { 1166 /// Return the length of valid data in the sockaddr structure. 1167 /// 1168 /// For fixed-size sockaddrs, this should be the size of the 1169 /// structure. But for variable-sized types like [`UnixAddr`] it 1170 /// may be less. 1171 fn len(&self) -> libc::socklen_t { 1172 // Safe since all implementors have a sa_len field at the same 1173 // address, and they're all repr(transparent). 1174 // Robust for all implementors. 1175 unsafe { 1176 (*(self as *const Self as *const libc::sockaddr)).sa_len 1177 }.into() 1178 } 1179 } else { 1180 /// Return the length of valid data in the sockaddr structure. 1181 /// 1182 /// For fixed-size sockaddrs, this should be the size of the 1183 /// structure. But for variable-sized types like [`UnixAddr`] it 1184 /// may be less. 1185 fn len(&self) -> libc::socklen_t { 1186 // No robust default implementation is possible without an 1187 // sa_len field. Implementors with a variable size must 1188 // override this method. 1189 mem::size_of_val(self) as libc::socklen_t 1190 } 1191 } 1192 } 1193 1194 /// Return the available space in the structure 1195 fn size() -> libc::socklen_t 1196 where 1197 Self: Sized, 1198 { 1199 mem::size_of::<Self>() as libc::socklen_t 1200 } 1201} 1202 1203impl private::SockaddrLikePriv for () { 1204 fn as_mut_ptr(&mut self) -> *mut libc::sockaddr { 1205 ptr::null_mut() 1206 } 1207} 1208 1209/// `()` can be used in place of a real Sockaddr when no address is expected, 1210/// for example for a field of `Option<S> where S: SockaddrLike`. 1211// If this RFC ever stabilizes, then ! will be a better choice. 1212// https://github.com/rust-lang/rust/issues/35121 1213impl SockaddrLike for () { 1214 fn as_ptr(&self) -> *const libc::sockaddr { 1215 ptr::null() 1216 } 1217 1218 unsafe fn from_raw( 1219 _: *const libc::sockaddr, 1220 _: Option<libc::socklen_t>, 1221 ) -> Option<Self> 1222 where 1223 Self: Sized, 1224 { 1225 None 1226 } 1227 1228 fn family(&self) -> Option<AddressFamily> { 1229 None 1230 } 1231 1232 fn len(&self) -> libc::socklen_t { 1233 0 1234 } 1235} 1236 1237/// An IPv4 socket address 1238// This is identical to net::SocketAddrV4. But the standard library 1239// doesn't allow direct access to the libc fields, which we need. So we 1240// reimplement it here. 1241#[cfg(feature = "net")] 1242#[repr(transparent)] 1243#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 1244pub struct SockaddrIn(libc::sockaddr_in); 1245 1246#[cfg(feature = "net")] 1247impl SockaddrIn { 1248 /// Returns the IP address associated with this socket address, in native 1249 /// endian. 1250 pub const fn ip(&self) -> libc::in_addr_t { 1251 u32::from_be(self.0.sin_addr.s_addr) 1252 } 1253 1254 /// Creates a new socket address from IPv4 octets and a port number. 1255 pub fn new(a: u8, b: u8, c: u8, d: u8, port: u16) -> Self { 1256 Self(libc::sockaddr_in { 1257 #[cfg(any( 1258 target_os = "dragonfly", 1259 target_os = "freebsd", 1260 target_os = "ios", 1261 target_os = "macos", 1262 target_os = "netbsd", 1263 target_os = "haiku", 1264 target_os = "openbsd" 1265 ))] 1266 sin_len: Self::size() as u8, 1267 sin_family: AddressFamily::Inet as sa_family_t, 1268 sin_port: u16::to_be(port), 1269 sin_addr: libc::in_addr { 1270 s_addr: u32::from_ne_bytes([a, b, c, d]), 1271 }, 1272 sin_zero: unsafe { mem::zeroed() }, 1273 }) 1274 } 1275 1276 /// Returns the port number associated with this socket address, in native 1277 /// endian. 1278 pub const fn port(&self) -> u16 { 1279 u16::from_be(self.0.sin_port) 1280 } 1281} 1282 1283#[cfg(feature = "net")] 1284impl private::SockaddrLikePriv for SockaddrIn {} 1285#[cfg(feature = "net")] 1286impl SockaddrLike for SockaddrIn { 1287 unsafe fn from_raw( 1288 addr: *const libc::sockaddr, 1289 len: Option<libc::socklen_t>, 1290 ) -> Option<Self> 1291 where 1292 Self: Sized, 1293 { 1294 if let Some(l) = len { 1295 if l != mem::size_of::<libc::sockaddr_in>() as libc::socklen_t { 1296 return None; 1297 } 1298 } 1299 if (*addr).sa_family as i32 != libc::AF_INET { 1300 return None; 1301 } 1302 Some(Self(ptr::read_unaligned(addr as *const _))) 1303 } 1304} 1305 1306#[cfg(feature = "net")] 1307impl AsRef<libc::sockaddr_in> for SockaddrIn { 1308 fn as_ref(&self) -> &libc::sockaddr_in { 1309 &self.0 1310 } 1311} 1312 1313#[cfg(feature = "net")] 1314impl fmt::Display for SockaddrIn { 1315 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1316 let ne = u32::from_be(self.0.sin_addr.s_addr); 1317 let port = u16::from_be(self.0.sin_port); 1318 write!( 1319 f, 1320 "{}.{}.{}.{}:{}", 1321 ne >> 24, 1322 (ne >> 16) & 0xFF, 1323 (ne >> 8) & 0xFF, 1324 ne & 0xFF, 1325 port 1326 ) 1327 } 1328} 1329 1330#[cfg(feature = "net")] 1331impl From<net::SocketAddrV4> for SockaddrIn { 1332 fn from(addr: net::SocketAddrV4) -> Self { 1333 Self(libc::sockaddr_in { 1334 #[cfg(any( 1335 target_os = "dragonfly", 1336 target_os = "freebsd", 1337 target_os = "haiku", 1338 target_os = "hermit", 1339 target_os = "ios", 1340 target_os = "macos", 1341 target_os = "netbsd", 1342 target_os = "openbsd" 1343 ))] 1344 sin_len: mem::size_of::<libc::sockaddr_in>() as u8, 1345 sin_family: AddressFamily::Inet as sa_family_t, 1346 sin_port: addr.port().to_be(), // network byte order 1347 sin_addr: ipv4addr_to_libc(*addr.ip()), 1348 ..unsafe { mem::zeroed() } 1349 }) 1350 } 1351} 1352 1353#[cfg(feature = "net")] 1354impl From<SockaddrIn> for net::SocketAddrV4 { 1355 fn from(addr: SockaddrIn) -> Self { 1356 net::SocketAddrV4::new( 1357 net::Ipv4Addr::from(addr.0.sin_addr.s_addr.to_ne_bytes()), 1358 u16::from_be(addr.0.sin_port), 1359 ) 1360 } 1361} 1362 1363#[cfg(feature = "net")] 1364impl std::str::FromStr for SockaddrIn { 1365 type Err = net::AddrParseError; 1366 1367 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { 1368 net::SocketAddrV4::from_str(s).map(SockaddrIn::from) 1369 } 1370} 1371 1372/// An IPv6 socket address 1373#[cfg(feature = "net")] 1374#[repr(transparent)] 1375#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 1376pub struct SockaddrIn6(libc::sockaddr_in6); 1377 1378#[cfg(feature = "net")] 1379impl SockaddrIn6 { 1380 /// Returns the flow information associated with this address. 1381 pub const fn flowinfo(&self) -> u32 { 1382 self.0.sin6_flowinfo 1383 } 1384 1385 /// Returns the IP address associated with this socket address. 1386 pub fn ip(&self) -> net::Ipv6Addr { 1387 net::Ipv6Addr::from(self.0.sin6_addr.s6_addr) 1388 } 1389 1390 /// Returns the port number associated with this socket address, in native 1391 /// endian. 1392 pub const fn port(&self) -> u16 { 1393 u16::from_be(self.0.sin6_port) 1394 } 1395 1396 /// Returns the scope ID associated with this address. 1397 pub const fn scope_id(&self) -> u32 { 1398 self.0.sin6_scope_id 1399 } 1400} 1401 1402#[cfg(feature = "net")] 1403impl private::SockaddrLikePriv for SockaddrIn6 {} 1404#[cfg(feature = "net")] 1405impl SockaddrLike for SockaddrIn6 { 1406 unsafe fn from_raw( 1407 addr: *const libc::sockaddr, 1408 len: Option<libc::socklen_t>, 1409 ) -> Option<Self> 1410 where 1411 Self: Sized, 1412 { 1413 if let Some(l) = len { 1414 if l != mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t { 1415 return None; 1416 } 1417 } 1418 if (*addr).sa_family as i32 != libc::AF_INET6 { 1419 return None; 1420 } 1421 Some(Self(ptr::read_unaligned(addr as *const _))) 1422 } 1423} 1424 1425#[cfg(feature = "net")] 1426impl AsRef<libc::sockaddr_in6> for SockaddrIn6 { 1427 fn as_ref(&self) -> &libc::sockaddr_in6 { 1428 &self.0 1429 } 1430} 1431 1432#[cfg(feature = "net")] 1433impl fmt::Display for SockaddrIn6 { 1434 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1435 // These things are really hard to display properly. Easier to let std 1436 // do it. 1437 let std = net::SocketAddrV6::new( 1438 self.ip(), 1439 self.port(), 1440 self.flowinfo(), 1441 self.scope_id(), 1442 ); 1443 std.fmt(f) 1444 } 1445} 1446 1447#[cfg(feature = "net")] 1448impl From<net::SocketAddrV6> for SockaddrIn6 { 1449 fn from(addr: net::SocketAddrV6) -> Self { 1450 #[allow(clippy::needless_update)] // It isn't needless on Illumos 1451 Self(libc::sockaddr_in6 { 1452 #[cfg(any( 1453 target_os = "dragonfly", 1454 target_os = "freebsd", 1455 target_os = "haiku", 1456 target_os = "hermit", 1457 target_os = "ios", 1458 target_os = "macos", 1459 target_os = "netbsd", 1460 target_os = "openbsd" 1461 ))] 1462 sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8, 1463 sin6_family: AddressFamily::Inet6 as sa_family_t, 1464 sin6_port: addr.port().to_be(), // network byte order 1465 sin6_addr: ipv6addr_to_libc(addr.ip()), 1466 sin6_flowinfo: addr.flowinfo(), // host byte order 1467 sin6_scope_id: addr.scope_id(), // host byte order 1468 ..unsafe { mem::zeroed() } 1469 }) 1470 } 1471} 1472 1473#[cfg(feature = "net")] 1474impl From<SockaddrIn6> for net::SocketAddrV6 { 1475 fn from(addr: SockaddrIn6) -> Self { 1476 net::SocketAddrV6::new( 1477 net::Ipv6Addr::from(addr.0.sin6_addr.s6_addr), 1478 u16::from_be(addr.0.sin6_port), 1479 addr.0.sin6_flowinfo, 1480 addr.0.sin6_scope_id, 1481 ) 1482 } 1483} 1484 1485#[cfg(feature = "net")] 1486impl std::str::FromStr for SockaddrIn6 { 1487 type Err = net::AddrParseError; 1488 1489 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { 1490 net::SocketAddrV6::from_str(s).map(SockaddrIn6::from) 1491 } 1492} 1493 1494/// A container for any sockaddr type 1495/// 1496/// Just like C's `sockaddr_storage`, this type is large enough to hold any type 1497/// of sockaddr. It can be used as an argument with functions like 1498/// [`bind`](super::bind) and [`getsockname`](super::getsockname). Though it is 1499/// a union, it can be safely accessed through the `as_*` methods. 1500/// 1501/// # Example 1502/// ``` 1503/// # use nix::sys::socket::*; 1504/// # use std::str::FromStr; 1505/// let localhost = SockaddrIn::from_str("127.0.0.1:8081").unwrap(); 1506/// let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), 1507/// None).unwrap(); 1508/// bind(fd, &localhost).expect("bind"); 1509/// let ss: SockaddrStorage = getsockname(fd).expect("getsockname"); 1510/// assert_eq!(&localhost, ss.as_sockaddr_in().unwrap()); 1511/// ``` 1512#[derive(Clone, Copy, Eq)] 1513#[repr(C)] 1514pub union SockaddrStorage { 1515 #[cfg(any(target_os = "android", target_os = "linux"))] 1516 #[cfg_attr(docsrs, doc(cfg(all())))] 1517 alg: AlgAddr, 1518 #[cfg(feature = "net")] 1519 #[cfg_attr(docsrs, doc(cfg(feature = "net")))] 1520 dl: LinkAddr, 1521 #[cfg(any(target_os = "android", target_os = "linux"))] 1522 nl: NetlinkAddr, 1523 #[cfg(all( 1524 feature = "ioctl", 1525 any(target_os = "ios", target_os = "macos") 1526 ))] 1527 #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))] 1528 sctl: SysControlAddr, 1529 #[cfg(feature = "net")] 1530 sin: SockaddrIn, 1531 #[cfg(feature = "net")] 1532 sin6: SockaddrIn6, 1533 ss: libc::sockaddr_storage, 1534 su: UnixAddr, 1535 #[cfg(any(target_os = "android", target_os = "linux"))] 1536 #[cfg_attr(docsrs, doc(cfg(all())))] 1537 vsock: VsockAddr, 1538} 1539impl private::SockaddrLikePriv for SockaddrStorage {} 1540impl SockaddrLike for SockaddrStorage { 1541 unsafe fn from_raw( 1542 addr: *const libc::sockaddr, 1543 l: Option<libc::socklen_t>, 1544 ) -> Option<Self> 1545 where 1546 Self: Sized, 1547 { 1548 if addr.is_null() { 1549 return None; 1550 } 1551 if let Some(len) = l { 1552 let ulen = len as usize; 1553 if ulen < offset_of!(libc::sockaddr, sa_data) 1554 || ulen > mem::size_of::<libc::sockaddr_storage>() 1555 { 1556 None 1557 } else { 1558 let mut ss: libc::sockaddr_storage = mem::zeroed(); 1559 let ssp = &mut ss as *mut libc::sockaddr_storage as *mut u8; 1560 ptr::copy(addr as *const u8, ssp, len as usize); 1561 #[cfg(any( 1562 target_os = "android", 1563 target_os = "fuchsia", 1564 target_os = "illumos", 1565 target_os = "linux" 1566 ))] 1567 if i32::from(ss.ss_family) == libc::AF_UNIX { 1568 // Safe because we UnixAddr is strictly smaller than 1569 // SockaddrStorage, and we just initialized the structure. 1570 (*(&mut ss as *mut libc::sockaddr_storage as *mut UnixAddr)).sun_len = len as u8; 1571 } 1572 Some(Self { ss }) 1573 } 1574 } else { 1575 // If length is not available and addr is of a fixed-length type, 1576 // copy it. If addr is of a variable length type and len is not 1577 // available, then there's nothing we can do. 1578 match (*addr).sa_family as i32 { 1579 #[cfg(any(target_os = "android", target_os = "linux"))] 1580 libc::AF_ALG => { 1581 AlgAddr::from_raw(addr, l).map(|alg| Self { alg }) 1582 } 1583 #[cfg(feature = "net")] 1584 libc::AF_INET => { 1585 SockaddrIn::from_raw(addr, l).map(|sin| Self { sin }) 1586 } 1587 #[cfg(feature = "net")] 1588 libc::AF_INET6 => { 1589 SockaddrIn6::from_raw(addr, l).map(|sin6| Self { sin6 }) 1590 } 1591 #[cfg(any( 1592 target_os = "dragonfly", 1593 target_os = "freebsd", 1594 target_os = "ios", 1595 target_os = "macos", 1596 target_os = "illumos", 1597 target_os = "netbsd", 1598 target_os = "haiku", 1599 target_os = "openbsd" 1600 ))] 1601 #[cfg(feature = "net")] 1602 libc::AF_LINK => { 1603 LinkAddr::from_raw(addr, l).map(|dl| Self { dl }) 1604 } 1605 #[cfg(any(target_os = "android", target_os = "linux"))] 1606 libc::AF_NETLINK => { 1607 NetlinkAddr::from_raw(addr, l).map(|nl| Self { nl }) 1608 } 1609 #[cfg(any( 1610 target_os = "android", 1611 target_os = "fuchsia", 1612 target_os = "linux" 1613 ))] 1614 #[cfg(feature = "net")] 1615 libc::AF_PACKET => { 1616 LinkAddr::from_raw(addr, l).map(|dl| Self { dl }) 1617 } 1618 #[cfg(all( 1619 feature = "ioctl", 1620 any(target_os = "ios", target_os = "macos") 1621 ))] 1622 libc::AF_SYSTEM => { 1623 SysControlAddr::from_raw(addr, l).map(|sctl| Self { sctl }) 1624 } 1625 #[cfg(any(target_os = "android", target_os = "linux"))] 1626 libc::AF_VSOCK => { 1627 VsockAddr::from_raw(addr, l).map(|vsock| Self { vsock }) 1628 } 1629 _ => None, 1630 } 1631 } 1632 } 1633 1634 #[cfg(any( 1635 target_os = "android", 1636 target_os = "fuchsia", 1637 target_os = "illumos", 1638 target_os = "linux" 1639 ))] 1640 fn len(&self) -> libc::socklen_t { 1641 match self.as_unix_addr() { 1642 // The UnixAddr type knows its own length 1643 Some(ua) => ua.len(), 1644 // For all else, we're just a boring SockaddrStorage 1645 None => mem::size_of_val(self) as libc::socklen_t 1646 } 1647 } 1648} 1649 1650macro_rules! accessors { 1651 ( 1652 $fname:ident, 1653 $fname_mut:ident, 1654 $sockty:ty, 1655 $family:expr, 1656 $libc_ty:ty, 1657 $field:ident) => { 1658 /// Safely and falliably downcast to an immutable reference 1659 pub fn $fname(&self) -> Option<&$sockty> { 1660 if self.family() == Some($family) 1661 && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t 1662 { 1663 // Safe because family and len are validated 1664 Some(unsafe { &self.$field }) 1665 } else { 1666 None 1667 } 1668 } 1669 1670 /// Safely and falliably downcast to a mutable reference 1671 pub fn $fname_mut(&mut self) -> Option<&mut $sockty> { 1672 if self.family() == Some($family) 1673 && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t 1674 { 1675 // Safe because family and len are validated 1676 Some(unsafe { &mut self.$field }) 1677 } else { 1678 None 1679 } 1680 } 1681 }; 1682} 1683 1684impl SockaddrStorage { 1685 /// Downcast to an immutable `[UnixAddr]` reference. 1686 pub fn as_unix_addr(&self) -> Option<&UnixAddr> { 1687 cfg_if! { 1688 if #[cfg(any(target_os = "android", 1689 target_os = "fuchsia", 1690 target_os = "illumos", 1691 target_os = "linux" 1692 ))] 1693 { 1694 let p = unsafe{ &self.ss as *const libc::sockaddr_storage }; 1695 // Safe because UnixAddr is strictly smaller than 1696 // sockaddr_storage, and we're fully initialized 1697 let len = unsafe { 1698 (*(p as *const UnixAddr )).sun_len as usize 1699 }; 1700 } else { 1701 let len = self.len() as usize; 1702 } 1703 } 1704 // Sanity checks 1705 if self.family() != Some(AddressFamily::Unix) || 1706 len < offset_of!(libc::sockaddr_un, sun_path) || 1707 len > mem::size_of::<libc::sockaddr_un>() { 1708 None 1709 } else { 1710 Some(unsafe{&self.su}) 1711 } 1712 } 1713 1714 /// Downcast to a mutable `[UnixAddr]` reference. 1715 pub fn as_unix_addr_mut(&mut self) -> Option<&mut UnixAddr> { 1716 cfg_if! { 1717 if #[cfg(any(target_os = "android", 1718 target_os = "fuchsia", 1719 target_os = "illumos", 1720 target_os = "linux" 1721 ))] 1722 { 1723 let p = unsafe{ &self.ss as *const libc::sockaddr_storage }; 1724 // Safe because UnixAddr is strictly smaller than 1725 // sockaddr_storage, and we're fully initialized 1726 let len = unsafe { 1727 (*(p as *const UnixAddr )).sun_len as usize 1728 }; 1729 } else { 1730 let len = self.len() as usize; 1731 } 1732 } 1733 // Sanity checks 1734 if self.family() != Some(AddressFamily::Unix) || 1735 len < offset_of!(libc::sockaddr_un, sun_path) || 1736 len > mem::size_of::<libc::sockaddr_un>() { 1737 None 1738 } else { 1739 Some(unsafe{&mut self.su}) 1740 } 1741 } 1742 1743 #[cfg(any(target_os = "android", target_os = "linux"))] 1744 accessors! {as_alg_addr, as_alg_addr_mut, AlgAddr, 1745 AddressFamily::Alg, libc::sockaddr_alg, alg} 1746 1747 #[cfg(any( 1748 target_os = "android", 1749 target_os = "fuchsia", 1750 target_os = "linux" 1751 ))] 1752 #[cfg(feature = "net")] 1753 accessors! { 1754 as_link_addr, as_link_addr_mut, LinkAddr, 1755 AddressFamily::Packet, libc::sockaddr_ll, dl} 1756 1757 #[cfg(any( 1758 target_os = "dragonfly", 1759 target_os = "freebsd", 1760 target_os = "ios", 1761 target_os = "macos", 1762 target_os = "illumos", 1763 target_os = "netbsd", 1764 target_os = "openbsd" 1765 ))] 1766 #[cfg(feature = "net")] 1767 accessors! { 1768 as_link_addr, as_link_addr_mut, LinkAddr, 1769 AddressFamily::Link, libc::sockaddr_dl, dl} 1770 1771 #[cfg(feature = "net")] 1772 accessors! { 1773 as_sockaddr_in, as_sockaddr_in_mut, SockaddrIn, 1774 AddressFamily::Inet, libc::sockaddr_in, sin} 1775 1776 #[cfg(feature = "net")] 1777 accessors! { 1778 as_sockaddr_in6, as_sockaddr_in6_mut, SockaddrIn6, 1779 AddressFamily::Inet6, libc::sockaddr_in6, sin6} 1780 1781 #[cfg(any(target_os = "android", target_os = "linux"))] 1782 accessors! {as_netlink_addr, as_netlink_addr_mut, NetlinkAddr, 1783 AddressFamily::Netlink, libc::sockaddr_nl, nl} 1784 1785 #[cfg(all(feature = "ioctl", any(target_os = "ios", target_os = "macos")))] 1786 #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))] 1787 accessors! {as_sys_control_addr, as_sys_control_addr_mut, SysControlAddr, 1788 AddressFamily::System, libc::sockaddr_ctl, sctl} 1789 1790 #[cfg(any(target_os = "android", target_os = "linux"))] 1791 #[cfg_attr(docsrs, doc(cfg(all())))] 1792 accessors! {as_vsock_addr, as_vsock_addr_mut, VsockAddr, 1793 AddressFamily::Vsock, libc::sockaddr_vm, vsock} 1794} 1795 1796impl fmt::Debug for SockaddrStorage { 1797 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1798 f.debug_struct("SockaddrStorage") 1799 // Safe because sockaddr_storage has the least specific 1800 // field types 1801 .field("ss", unsafe { &self.ss }) 1802 .finish() 1803 } 1804} 1805 1806impl fmt::Display for SockaddrStorage { 1807 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1808 unsafe { 1809 match self.ss.ss_family as i32 { 1810 #[cfg(any(target_os = "android", target_os = "linux"))] 1811 libc::AF_ALG => self.alg.fmt(f), 1812 #[cfg(feature = "net")] 1813 libc::AF_INET => self.sin.fmt(f), 1814 #[cfg(feature = "net")] 1815 libc::AF_INET6 => self.sin6.fmt(f), 1816 #[cfg(any( 1817 target_os = "dragonfly", 1818 target_os = "freebsd", 1819 target_os = "ios", 1820 target_os = "macos", 1821 target_os = "illumos", 1822 target_os = "netbsd", 1823 target_os = "openbsd" 1824 ))] 1825 #[cfg(feature = "net")] 1826 libc::AF_LINK => self.dl.fmt(f), 1827 #[cfg(any(target_os = "android", target_os = "linux"))] 1828 libc::AF_NETLINK => self.nl.fmt(f), 1829 #[cfg(any( 1830 target_os = "android", 1831 target_os = "linux", 1832 target_os = "fuchsia" 1833 ))] 1834 #[cfg(feature = "net")] 1835 libc::AF_PACKET => self.dl.fmt(f), 1836 #[cfg(any(target_os = "ios", target_os = "macos"))] 1837 #[cfg(feature = "ioctl")] 1838 libc::AF_SYSTEM => self.sctl.fmt(f), 1839 libc::AF_UNIX => self.su.fmt(f), 1840 #[cfg(any(target_os = "android", target_os = "linux"))] 1841 libc::AF_VSOCK => self.vsock.fmt(f), 1842 _ => "<Address family unspecified>".fmt(f), 1843 } 1844 } 1845 } 1846} 1847 1848#[cfg(feature = "net")] 1849impl From<net::SocketAddrV4> for SockaddrStorage { 1850 fn from(s: net::SocketAddrV4) -> Self { 1851 unsafe { 1852 let mut ss: Self = mem::zeroed(); 1853 ss.sin = SockaddrIn::from(s); 1854 ss 1855 } 1856 } 1857} 1858 1859#[cfg(feature = "net")] 1860impl From<net::SocketAddrV6> for SockaddrStorage { 1861 fn from(s: net::SocketAddrV6) -> Self { 1862 unsafe { 1863 let mut ss: Self = mem::zeroed(); 1864 ss.sin6 = SockaddrIn6::from(s); 1865 ss 1866 } 1867 } 1868} 1869 1870#[cfg(feature = "net")] 1871impl From<net::SocketAddr> for SockaddrStorage { 1872 fn from(s: net::SocketAddr) -> Self { 1873 match s { 1874 net::SocketAddr::V4(sa4) => Self::from(sa4), 1875 net::SocketAddr::V6(sa6) => Self::from(sa6), 1876 } 1877 } 1878} 1879 1880impl Hash for SockaddrStorage { 1881 fn hash<H: Hasher>(&self, s: &mut H) { 1882 unsafe { 1883 match self.ss.ss_family as i32 { 1884 #[cfg(any(target_os = "android", target_os = "linux"))] 1885 libc::AF_ALG => self.alg.hash(s), 1886 #[cfg(feature = "net")] 1887 libc::AF_INET => self.sin.hash(s), 1888 #[cfg(feature = "net")] 1889 libc::AF_INET6 => self.sin6.hash(s), 1890 #[cfg(any( 1891 target_os = "dragonfly", 1892 target_os = "freebsd", 1893 target_os = "ios", 1894 target_os = "macos", 1895 target_os = "illumos", 1896 target_os = "netbsd", 1897 target_os = "openbsd" 1898 ))] 1899 #[cfg(feature = "net")] 1900 libc::AF_LINK => self.dl.hash(s), 1901 #[cfg(any(target_os = "android", target_os = "linux"))] 1902 libc::AF_NETLINK => self.nl.hash(s), 1903 #[cfg(any( 1904 target_os = "android", 1905 target_os = "linux", 1906 target_os = "fuchsia" 1907 ))] 1908 #[cfg(feature = "net")] 1909 libc::AF_PACKET => self.dl.hash(s), 1910 #[cfg(any(target_os = "ios", target_os = "macos"))] 1911 #[cfg(feature = "ioctl")] 1912 libc::AF_SYSTEM => self.sctl.hash(s), 1913 libc::AF_UNIX => self.su.hash(s), 1914 #[cfg(any(target_os = "android", target_os = "linux"))] 1915 libc::AF_VSOCK => self.vsock.hash(s), 1916 _ => self.ss.hash(s), 1917 } 1918 } 1919 } 1920} 1921 1922impl PartialEq for SockaddrStorage { 1923 fn eq(&self, other: &Self) -> bool { 1924 unsafe { 1925 match (self.ss.ss_family as i32, other.ss.ss_family as i32) { 1926 #[cfg(any(target_os = "android", target_os = "linux"))] 1927 (libc::AF_ALG, libc::AF_ALG) => self.alg == other.alg, 1928 #[cfg(feature = "net")] 1929 (libc::AF_INET, libc::AF_INET) => self.sin == other.sin, 1930 #[cfg(feature = "net")] 1931 (libc::AF_INET6, libc::AF_INET6) => self.sin6 == other.sin6, 1932 #[cfg(any( 1933 target_os = "dragonfly", 1934 target_os = "freebsd", 1935 target_os = "ios", 1936 target_os = "macos", 1937 target_os = "illumos", 1938 target_os = "netbsd", 1939 target_os = "openbsd" 1940 ))] 1941 #[cfg(feature = "net")] 1942 (libc::AF_LINK, libc::AF_LINK) => self.dl == other.dl, 1943 #[cfg(any(target_os = "android", target_os = "linux"))] 1944 (libc::AF_NETLINK, libc::AF_NETLINK) => self.nl == other.nl, 1945 #[cfg(any( 1946 target_os = "android", 1947 target_os = "fuchsia", 1948 target_os = "linux" 1949 ))] 1950 #[cfg(feature = "net")] 1951 (libc::AF_PACKET, libc::AF_PACKET) => self.dl == other.dl, 1952 #[cfg(any(target_os = "ios", target_os = "macos"))] 1953 #[cfg(feature = "ioctl")] 1954 (libc::AF_SYSTEM, libc::AF_SYSTEM) => self.sctl == other.sctl, 1955 (libc::AF_UNIX, libc::AF_UNIX) => self.su == other.su, 1956 #[cfg(any(target_os = "android", target_os = "linux"))] 1957 (libc::AF_VSOCK, libc::AF_VSOCK) => self.vsock == other.vsock, 1958 _ => false, 1959 } 1960 } 1961 } 1962} 1963 1964mod private { 1965 pub trait SockaddrLikePriv { 1966 /// Returns a mutable raw pointer to the inner structure. 1967 /// 1968 /// # Safety 1969 /// 1970 /// This method is technically safe, but modifying the inner structure's 1971 /// `family` or `len` fields may result in violating Nix's invariants. 1972 /// It is best to use this method only with foreign functions that do 1973 /// not change the sockaddr type. 1974 fn as_mut_ptr(&mut self) -> *mut libc::sockaddr { 1975 self as *mut Self as *mut libc::sockaddr 1976 } 1977 } 1978} 1979 1980/// Represents a socket address 1981#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 1982#[deprecated( 1983 since = "0.24.0", 1984 note = "use SockaddrLike or SockaddrStorage instead" 1985)] 1986#[allow(missing_docs)] // Since they're all deprecated anyway 1987#[allow(deprecated)] 1988#[non_exhaustive] 1989pub enum SockAddr { 1990 #[cfg(feature = "net")] 1991 #[cfg_attr(docsrs, doc(cfg(feature = "net")))] 1992 Inet(InetAddr), 1993 Unix(UnixAddr), 1994 #[cfg(any(target_os = "android", target_os = "linux"))] 1995 #[cfg_attr(docsrs, doc(cfg(all())))] 1996 Netlink(NetlinkAddr), 1997 #[cfg(any(target_os = "android", target_os = "linux"))] 1998 #[cfg_attr(docsrs, doc(cfg(all())))] 1999 Alg(AlgAddr), 2000 #[cfg(all( 2001 feature = "ioctl", 2002 any(target_os = "ios", target_os = "macos") 2003 ))] 2004 #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))] 2005 SysControl(SysControlAddr), 2006 /// Datalink address (MAC) 2007 #[cfg(any( 2008 target_os = "android", 2009 target_os = "dragonfly", 2010 target_os = "freebsd", 2011 target_os = "ios", 2012 target_os = "linux", 2013 target_os = "macos", 2014 target_os = "illumos", 2015 target_os = "netbsd", 2016 target_os = "openbsd" 2017 ))] 2018 #[cfg(feature = "net")] 2019 #[cfg_attr(docsrs, doc(cfg(feature = "net")))] 2020 Link(LinkAddr), 2021 #[cfg(any(target_os = "android", target_os = "linux"))] 2022 #[cfg_attr(docsrs, doc(cfg(all())))] 2023 Vsock(VsockAddr), 2024} 2025 2026#[allow(missing_docs)] // Since they're all deprecated anyway 2027#[allow(deprecated)] 2028impl SockAddr { 2029 feature! { 2030 #![feature = "net"] 2031 pub fn new_inet(addr: InetAddr) -> SockAddr { 2032 SockAddr::Inet(addr) 2033 } 2034 } 2035 2036 pub fn new_unix<P: ?Sized + NixPath>(path: &P) -> Result<SockAddr> { 2037 Ok(SockAddr::Unix(UnixAddr::new(path)?)) 2038 } 2039 2040 #[cfg(any(target_os = "android", target_os = "linux"))] 2041 #[cfg_attr(docsrs, doc(cfg(all())))] 2042 pub fn new_netlink(pid: u32, groups: u32) -> SockAddr { 2043 SockAddr::Netlink(NetlinkAddr::new(pid, groups)) 2044 } 2045 2046 #[cfg(any(target_os = "android", target_os = "linux"))] 2047 #[cfg_attr(docsrs, doc(cfg(all())))] 2048 pub fn new_alg(alg_type: &str, alg_name: &str) -> SockAddr { 2049 SockAddr::Alg(AlgAddr::new(alg_type, alg_name)) 2050 } 2051 2052 feature! { 2053 #![feature = "ioctl"] 2054 #[cfg(any(target_os = "ios", target_os = "macos"))] 2055 pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> { 2056 SysControlAddr::from_name(sockfd, name, unit).map(SockAddr::SysControl) 2057 } 2058 } 2059 2060 #[cfg(any(target_os = "android", target_os = "linux"))] 2061 #[cfg_attr(docsrs, doc(cfg(all())))] 2062 pub fn new_vsock(cid: u32, port: u32) -> SockAddr { 2063 SockAddr::Vsock(VsockAddr::new(cid, port)) 2064 } 2065 2066 pub fn family(&self) -> AddressFamily { 2067 match *self { 2068 #[cfg(feature = "net")] 2069 SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet, 2070 #[cfg(feature = "net")] 2071 SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6, 2072 SockAddr::Unix(..) => AddressFamily::Unix, 2073 #[cfg(any(target_os = "android", target_os = "linux"))] 2074 SockAddr::Netlink(..) => AddressFamily::Netlink, 2075 #[cfg(any(target_os = "android", target_os = "linux"))] 2076 SockAddr::Alg(..) => AddressFamily::Alg, 2077 #[cfg(all( 2078 feature = "ioctl", 2079 any(target_os = "ios", target_os = "macos") 2080 ))] 2081 SockAddr::SysControl(..) => AddressFamily::System, 2082 #[cfg(any(target_os = "android", target_os = "linux"))] 2083 #[cfg(feature = "net")] 2084 SockAddr::Link(..) => AddressFamily::Packet, 2085 #[cfg(any( 2086 target_os = "dragonfly", 2087 target_os = "freebsd", 2088 target_os = "ios", 2089 target_os = "macos", 2090 target_os = "netbsd", 2091 target_os = "illumos", 2092 target_os = "openbsd" 2093 ))] 2094 #[cfg(feature = "net")] 2095 SockAddr::Link(..) => AddressFamily::Link, 2096 #[cfg(any(target_os = "android", target_os = "linux"))] 2097 SockAddr::Vsock(..) => AddressFamily::Vsock, 2098 } 2099 } 2100 2101 #[deprecated(since = "0.23.0", note = "use .to_string() instead")] 2102 pub fn to_str(&self) -> String { 2103 format!("{}", self) 2104 } 2105 2106 /// Creates a `SockAddr` struct from libc's sockaddr. 2107 /// 2108 /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System. 2109 /// Returns None for unsupported families. 2110 /// 2111 /// # Safety 2112 /// 2113 /// unsafe because it takes a raw pointer as argument. The caller must 2114 /// ensure that the pointer is valid. 2115 #[cfg(not(target_os = "fuchsia"))] 2116 #[cfg(feature = "net")] 2117 pub(crate) unsafe fn from_libc_sockaddr( 2118 addr: *const libc::sockaddr, 2119 ) -> Option<SockAddr> { 2120 if addr.is_null() { 2121 None 2122 } else { 2123 match AddressFamily::from_i32(i32::from((*addr).sa_family)) { 2124 Some(AddressFamily::Unix) => None, 2125 #[cfg(feature = "net")] 2126 Some(AddressFamily::Inet) => Some(SockAddr::Inet( 2127 InetAddr::V4(ptr::read_unaligned(addr as *const _)), 2128 )), 2129 #[cfg(feature = "net")] 2130 Some(AddressFamily::Inet6) => Some(SockAddr::Inet( 2131 InetAddr::V6(ptr::read_unaligned(addr as *const _)), 2132 )), 2133 #[cfg(any(target_os = "android", target_os = "linux"))] 2134 Some(AddressFamily::Netlink) => Some(SockAddr::Netlink( 2135 NetlinkAddr(ptr::read_unaligned(addr as *const _)), 2136 )), 2137 #[cfg(all( 2138 feature = "ioctl", 2139 any(target_os = "ios", target_os = "macos") 2140 ))] 2141 Some(AddressFamily::System) => Some(SockAddr::SysControl( 2142 SysControlAddr(ptr::read_unaligned(addr as *const _)), 2143 )), 2144 #[cfg(any(target_os = "android", target_os = "linux"))] 2145 #[cfg(feature = "net")] 2146 Some(AddressFamily::Packet) => Some(SockAddr::Link(LinkAddr( 2147 ptr::read_unaligned(addr as *const _), 2148 ))), 2149 #[cfg(any( 2150 target_os = "dragonfly", 2151 target_os = "freebsd", 2152 target_os = "ios", 2153 target_os = "macos", 2154 target_os = "netbsd", 2155 target_os = "illumos", 2156 target_os = "openbsd" 2157 ))] 2158 #[cfg(feature = "net")] 2159 Some(AddressFamily::Link) => { 2160 let ether_addr = 2161 LinkAddr(ptr::read_unaligned(addr as *const _)); 2162 if ether_addr.is_empty() { 2163 None 2164 } else { 2165 Some(SockAddr::Link(ether_addr)) 2166 } 2167 } 2168 #[cfg(any(target_os = "android", target_os = "linux"))] 2169 Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(VsockAddr( 2170 ptr::read_unaligned(addr as *const _), 2171 ))), 2172 // Other address families are currently not supported and simply yield a None 2173 // entry instead of a proper conversion to a `SockAddr`. 2174 Some(_) | None => None, 2175 } 2176 } 2177 } 2178 2179 /// Conversion from nix's SockAddr type to the underlying libc sockaddr type. 2180 /// 2181 /// This is useful for interfacing with other libc functions that don't yet have nix wrappers. 2182 /// Returns a reference to the underlying data type (as a sockaddr reference) along 2183 /// with the size of the actual data type. sockaddr is commonly used as a proxy for 2184 /// a superclass as C doesn't support inheritance, so many functions that take 2185 /// a sockaddr * need to take the size of the underlying type as well and then internally cast it back. 2186 pub fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) { 2187 match *self { 2188 #[cfg(feature = "net")] 2189 SockAddr::Inet(InetAddr::V4(ref addr)) => ( 2190 // This cast is always allowed in C 2191 unsafe { 2192 &*(addr as *const libc::sockaddr_in 2193 as *const libc::sockaddr) 2194 }, 2195 mem::size_of_val(addr) as libc::socklen_t, 2196 ), 2197 #[cfg(feature = "net")] 2198 SockAddr::Inet(InetAddr::V6(ref addr)) => ( 2199 // This cast is always allowed in C 2200 unsafe { 2201 &*(addr as *const libc::sockaddr_in6 2202 as *const libc::sockaddr) 2203 }, 2204 mem::size_of_val(addr) as libc::socklen_t, 2205 ), 2206 SockAddr::Unix(ref unix_addr) => ( 2207 // This cast is always allowed in C 2208 unsafe { 2209 &*(&unix_addr.sun as *const libc::sockaddr_un 2210 as *const libc::sockaddr) 2211 }, 2212 unix_addr.sun_len() as libc::socklen_t, 2213 ), 2214 #[cfg(any(target_os = "android", target_os = "linux"))] 2215 SockAddr::Netlink(NetlinkAddr(ref sa)) => ( 2216 // This cast is always allowed in C 2217 unsafe { 2218 &*(sa as *const libc::sockaddr_nl as *const libc::sockaddr) 2219 }, 2220 mem::size_of_val(sa) as libc::socklen_t, 2221 ), 2222 #[cfg(any(target_os = "android", target_os = "linux"))] 2223 SockAddr::Alg(AlgAddr(ref sa)) => ( 2224 // This cast is always allowed in C 2225 unsafe { 2226 &*(sa as *const libc::sockaddr_alg as *const libc::sockaddr) 2227 }, 2228 mem::size_of_val(sa) as libc::socklen_t, 2229 ), 2230 #[cfg(all( 2231 feature = "ioctl", 2232 any(target_os = "ios", target_os = "macos") 2233 ))] 2234 SockAddr::SysControl(SysControlAddr(ref sa)) => ( 2235 // This cast is always allowed in C 2236 unsafe { 2237 &*(sa as *const libc::sockaddr_ctl as *const libc::sockaddr) 2238 }, 2239 mem::size_of_val(sa) as libc::socklen_t, 2240 ), 2241 #[cfg(any(target_os = "android", target_os = "linux"))] 2242 #[cfg(feature = "net")] 2243 SockAddr::Link(LinkAddr(ref addr)) => ( 2244 // This cast is always allowed in C 2245 unsafe { 2246 &*(addr as *const libc::sockaddr_ll 2247 as *const libc::sockaddr) 2248 }, 2249 mem::size_of_val(addr) as libc::socklen_t, 2250 ), 2251 #[cfg(any( 2252 target_os = "dragonfly", 2253 target_os = "freebsd", 2254 target_os = "ios", 2255 target_os = "macos", 2256 target_os = "illumos", 2257 target_os = "netbsd", 2258 target_os = "openbsd" 2259 ))] 2260 #[cfg(feature = "net")] 2261 SockAddr::Link(LinkAddr(ref addr)) => ( 2262 // This cast is always allowed in C 2263 unsafe { 2264 &*(addr as *const libc::sockaddr_dl 2265 as *const libc::sockaddr) 2266 }, 2267 mem::size_of_val(addr) as libc::socklen_t, 2268 ), 2269 #[cfg(any(target_os = "android", target_os = "linux"))] 2270 SockAddr::Vsock(VsockAddr(ref sa)) => ( 2271 // This cast is always allowed in C 2272 unsafe { 2273 &*(sa as *const libc::sockaddr_vm as *const libc::sockaddr) 2274 }, 2275 mem::size_of_val(sa) as libc::socklen_t, 2276 ), 2277 } 2278 } 2279} 2280 2281#[allow(deprecated)] 2282impl fmt::Display for SockAddr { 2283 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 2284 match *self { 2285 #[cfg(feature = "net")] 2286 SockAddr::Inet(ref inet) => inet.fmt(f), 2287 SockAddr::Unix(ref unix) => unix.fmt(f), 2288 #[cfg(any(target_os = "android", target_os = "linux"))] 2289 SockAddr::Netlink(ref nl) => nl.fmt(f), 2290 #[cfg(any(target_os = "android", target_os = "linux"))] 2291 SockAddr::Alg(ref nl) => nl.fmt(f), 2292 #[cfg(all( 2293 feature = "ioctl", 2294 any(target_os = "ios", target_os = "macos") 2295 ))] 2296 SockAddr::SysControl(ref sc) => sc.fmt(f), 2297 #[cfg(any( 2298 target_os = "android", 2299 target_os = "dragonfly", 2300 target_os = "freebsd", 2301 target_os = "ios", 2302 target_os = "linux", 2303 target_os = "macos", 2304 target_os = "netbsd", 2305 target_os = "illumos", 2306 target_os = "openbsd" 2307 ))] 2308 #[cfg(feature = "net")] 2309 SockAddr::Link(ref ether_addr) => ether_addr.fmt(f), 2310 #[cfg(any(target_os = "android", target_os = "linux"))] 2311 SockAddr::Vsock(ref svm) => svm.fmt(f), 2312 } 2313 } 2314} 2315 2316#[cfg(not(target_os = "fuchsia"))] 2317#[cfg(feature = "net")] 2318#[allow(deprecated)] 2319impl private::SockaddrLikePriv for SockAddr {} 2320#[cfg(not(target_os = "fuchsia"))] 2321#[cfg(feature = "net")] 2322#[allow(deprecated)] 2323impl SockaddrLike for SockAddr { 2324 unsafe fn from_raw( 2325 addr: *const libc::sockaddr, 2326 _len: Option<libc::socklen_t>, 2327 ) -> Option<Self> { 2328 Self::from_libc_sockaddr(addr) 2329 } 2330} 2331 2332#[cfg(any(target_os = "android", target_os = "linux"))] 2333#[cfg_attr(docsrs, doc(cfg(all())))] 2334pub mod netlink { 2335 use super::*; 2336 use crate::sys::socket::addr::AddressFamily; 2337 use libc::{sa_family_t, sockaddr_nl}; 2338 use std::{fmt, mem}; 2339 2340 /// Address for the Linux kernel user interface device. 2341 /// 2342 /// # References 2343 /// 2344 /// [netlink(7)](https://man7.org/linux/man-pages/man7/netlink.7.html) 2345 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] 2346 #[repr(transparent)] 2347 pub struct NetlinkAddr(pub(in super::super) sockaddr_nl); 2348 2349 impl NetlinkAddr { 2350 /// Construct a new socket address from its port ID and multicast groups 2351 /// mask. 2352 pub fn new(pid: u32, groups: u32) -> NetlinkAddr { 2353 let mut addr: sockaddr_nl = unsafe { mem::zeroed() }; 2354 addr.nl_family = AddressFamily::Netlink as sa_family_t; 2355 addr.nl_pid = pid; 2356 addr.nl_groups = groups; 2357 2358 NetlinkAddr(addr) 2359 } 2360 2361 /// Return the socket's port ID. 2362 pub const fn pid(&self) -> u32 { 2363 self.0.nl_pid 2364 } 2365 2366 /// Return the socket's multicast groups mask 2367 pub const fn groups(&self) -> u32 { 2368 self.0.nl_groups 2369 } 2370 } 2371 2372 impl private::SockaddrLikePriv for NetlinkAddr {} 2373 impl SockaddrLike for NetlinkAddr { 2374 unsafe fn from_raw( 2375 addr: *const libc::sockaddr, 2376 len: Option<libc::socklen_t>, 2377 ) -> Option<Self> 2378 where 2379 Self: Sized, 2380 { 2381 if let Some(l) = len { 2382 if l != mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t { 2383 return None; 2384 } 2385 } 2386 if (*addr).sa_family as i32 != libc::AF_NETLINK { 2387 return None; 2388 } 2389 Some(Self(ptr::read_unaligned(addr as *const _))) 2390 } 2391 } 2392 2393 impl AsRef<libc::sockaddr_nl> for NetlinkAddr { 2394 fn as_ref(&self) -> &libc::sockaddr_nl { 2395 &self.0 2396 } 2397 } 2398 2399 impl fmt::Display for NetlinkAddr { 2400 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 2401 write!(f, "pid: {} groups: {}", self.pid(), self.groups()) 2402 } 2403 } 2404} 2405 2406#[cfg(any(target_os = "android", target_os = "linux"))] 2407#[cfg_attr(docsrs, doc(cfg(all())))] 2408pub mod alg { 2409 use super::*; 2410 use libc::{c_char, sockaddr_alg, AF_ALG}; 2411 use std::ffi::CStr; 2412 use std::hash::{Hash, Hasher}; 2413 use std::{fmt, mem, str}; 2414 2415 /// Socket address for the Linux kernel crypto API 2416 #[derive(Copy, Clone)] 2417 #[repr(transparent)] 2418 pub struct AlgAddr(pub(in super::super) sockaddr_alg); 2419 2420 impl private::SockaddrLikePriv for AlgAddr {} 2421 impl SockaddrLike for AlgAddr { 2422 unsafe fn from_raw( 2423 addr: *const libc::sockaddr, 2424 l: Option<libc::socklen_t>, 2425 ) -> Option<Self> 2426 where 2427 Self: Sized, 2428 { 2429 if let Some(l) = l { 2430 if l != mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t 2431 { 2432 return None; 2433 } 2434 } 2435 if (*addr).sa_family as i32 != libc::AF_ALG { 2436 return None; 2437 } 2438 Some(Self(ptr::read_unaligned(addr as *const _))) 2439 } 2440 } 2441 2442 impl AsRef<libc::sockaddr_alg> for AlgAddr { 2443 fn as_ref(&self) -> &libc::sockaddr_alg { 2444 &self.0 2445 } 2446 } 2447 2448 // , PartialEq, Eq, Debug, Hash 2449 impl PartialEq for AlgAddr { 2450 fn eq(&self, other: &Self) -> bool { 2451 let (inner, other) = (self.0, other.0); 2452 ( 2453 inner.salg_family, 2454 &inner.salg_type[..], 2455 inner.salg_feat, 2456 inner.salg_mask, 2457 &inner.salg_name[..], 2458 ) == ( 2459 other.salg_family, 2460 &other.salg_type[..], 2461 other.salg_feat, 2462 other.salg_mask, 2463 &other.salg_name[..], 2464 ) 2465 } 2466 } 2467 2468 impl Eq for AlgAddr {} 2469 2470 impl Hash for AlgAddr { 2471 fn hash<H: Hasher>(&self, s: &mut H) { 2472 let inner = self.0; 2473 ( 2474 inner.salg_family, 2475 &inner.salg_type[..], 2476 inner.salg_feat, 2477 inner.salg_mask, 2478 &inner.salg_name[..], 2479 ) 2480 .hash(s); 2481 } 2482 } 2483 2484 impl AlgAddr { 2485 /// Construct an `AF_ALG` socket from its cipher name and type. 2486 pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr { 2487 let mut addr: sockaddr_alg = unsafe { mem::zeroed() }; 2488 addr.salg_family = AF_ALG as u16; 2489 addr.salg_type[..alg_type.len()] 2490 .copy_from_slice(alg_type.to_string().as_bytes()); 2491 addr.salg_name[..alg_name.len()] 2492 .copy_from_slice(alg_name.to_string().as_bytes()); 2493 2494 AlgAddr(addr) 2495 } 2496 2497 /// Return the socket's cipher type, for example `hash` or `aead`. 2498 pub fn alg_type(&self) -> &CStr { 2499 unsafe { 2500 CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char) 2501 } 2502 } 2503 2504 /// Return the socket's cipher name, for example `sha1`. 2505 pub fn alg_name(&self) -> &CStr { 2506 unsafe { 2507 CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char) 2508 } 2509 } 2510 } 2511 2512 impl fmt::Display for AlgAddr { 2513 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 2514 write!( 2515 f, 2516 "type: {} alg: {}", 2517 self.alg_name().to_string_lossy(), 2518 self.alg_type().to_string_lossy() 2519 ) 2520 } 2521 } 2522 2523 impl fmt::Debug for AlgAddr { 2524 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 2525 fmt::Display::fmt(self, f) 2526 } 2527 } 2528} 2529 2530feature! { 2531#![feature = "ioctl"] 2532#[cfg(any(target_os = "ios", target_os = "macos"))] 2533pub mod sys_control { 2534 use crate::sys::socket::addr::AddressFamily; 2535 use libc::{self, c_uchar}; 2536 use std::{fmt, mem, ptr}; 2537 use std::os::unix::io::RawFd; 2538 use crate::{Errno, Result}; 2539 use super::{private, SockaddrLike}; 2540 2541 // FIXME: Move type into `libc` 2542 #[repr(C)] 2543 #[derive(Clone, Copy)] 2544 #[allow(missing_debug_implementations)] 2545 pub struct ctl_ioc_info { 2546 pub ctl_id: u32, 2547 pub ctl_name: [c_uchar; MAX_KCTL_NAME], 2548 } 2549 2550 const CTL_IOC_MAGIC: u8 = b'N'; 2551 const CTL_IOC_INFO: u8 = 3; 2552 const MAX_KCTL_NAME: usize = 96; 2553 2554 ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info); 2555 2556 /// Apple system control socket 2557 /// 2558 /// # References 2559 /// 2560 /// <https://developer.apple.com/documentation/kernel/sockaddr_ctl> 2561 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 2562 #[repr(transparent)] 2563 pub struct SysControlAddr(pub(in super::super) libc::sockaddr_ctl); 2564 2565 impl private::SockaddrLikePriv for SysControlAddr {} 2566 impl SockaddrLike for SysControlAddr { 2567 unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>) 2568 -> Option<Self> where Self: Sized 2569 { 2570 if let Some(l) = len { 2571 if l != mem::size_of::<libc::sockaddr_ctl>() as libc::socklen_t { 2572 return None; 2573 } 2574 } 2575 if (*addr).sa_family as i32 != libc::AF_SYSTEM { 2576 return None; 2577 } 2578 Some(Self(ptr::read_unaligned(addr as *const _))) 2579 } 2580 } 2581 2582 impl AsRef<libc::sockaddr_ctl> for SysControlAddr { 2583 fn as_ref(&self) -> &libc::sockaddr_ctl { 2584 &self.0 2585 } 2586 } 2587 2588 impl SysControlAddr { 2589 /// Construct a new `SysControlAddr` from its kernel unique identifier 2590 /// and unit number. 2591 pub const fn new(id: u32, unit: u32) -> SysControlAddr { 2592 let addr = libc::sockaddr_ctl { 2593 sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar, 2594 sc_family: AddressFamily::System as c_uchar, 2595 ss_sysaddr: libc::AF_SYS_CONTROL as u16, 2596 sc_id: id, 2597 sc_unit: unit, 2598 sc_reserved: [0; 5] 2599 }; 2600 2601 SysControlAddr(addr) 2602 } 2603 2604 /// Construct a new `SysControlAddr` from its human readable name and 2605 /// unit number. 2606 pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> { 2607 if name.len() > MAX_KCTL_NAME { 2608 return Err(Errno::ENAMETOOLONG); 2609 } 2610 2611 let mut ctl_name = [0; MAX_KCTL_NAME]; 2612 ctl_name[..name.len()].clone_from_slice(name.as_bytes()); 2613 let mut info = ctl_ioc_info { ctl_id: 0, ctl_name }; 2614 2615 unsafe { ctl_info(sockfd, &mut info)?; } 2616 2617 Ok(SysControlAddr::new(info.ctl_id, unit)) 2618 } 2619 2620 /// Return the kernel unique identifier 2621 pub const fn id(&self) -> u32 { 2622 self.0.sc_id 2623 } 2624 2625 /// Return the kernel controller private unit number. 2626 pub const fn unit(&self) -> u32 { 2627 self.0.sc_unit 2628 } 2629 } 2630 2631 impl fmt::Display for SysControlAddr { 2632 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 2633 fmt::Debug::fmt(self, f) 2634 } 2635 } 2636} 2637} 2638 2639#[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))] 2640#[cfg_attr(docsrs, doc(cfg(all())))] 2641mod datalink { 2642 feature! { 2643 #![feature = "net"] 2644 use super::{fmt, mem, private, ptr, SockaddrLike}; 2645 2646 /// Hardware Address 2647 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 2648 #[repr(transparent)] 2649 pub struct LinkAddr(pub(in super::super) libc::sockaddr_ll); 2650 2651 impl LinkAddr { 2652 /// Physical-layer protocol 2653 pub fn protocol(&self) -> u16 { 2654 self.0.sll_protocol 2655 } 2656 2657 /// Interface number 2658 pub fn ifindex(&self) -> usize { 2659 self.0.sll_ifindex as usize 2660 } 2661 2662 /// ARP hardware type 2663 pub fn hatype(&self) -> u16 { 2664 self.0.sll_hatype 2665 } 2666 2667 /// Packet type 2668 pub fn pkttype(&self) -> u8 { 2669 self.0.sll_pkttype 2670 } 2671 2672 /// Length of MAC address 2673 pub fn halen(&self) -> usize { 2674 self.0.sll_halen as usize 2675 } 2676 2677 /// Physical-layer address (MAC) 2678 // Returns an Option just for cross-platform compatibility 2679 pub fn addr(&self) -> Option<[u8; 6]> { 2680 Some([ 2681 self.0.sll_addr[0], 2682 self.0.sll_addr[1], 2683 self.0.sll_addr[2], 2684 self.0.sll_addr[3], 2685 self.0.sll_addr[4], 2686 self.0.sll_addr[5], 2687 ]) 2688 } 2689 } 2690 2691 impl fmt::Display for LinkAddr { 2692 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 2693 if let Some(addr) = self.addr() { 2694 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", 2695 addr[0], 2696 addr[1], 2697 addr[2], 2698 addr[3], 2699 addr[4], 2700 addr[5]) 2701 } else { 2702 Ok(()) 2703 } 2704 } 2705 } 2706 impl private::SockaddrLikePriv for LinkAddr {} 2707 impl SockaddrLike for LinkAddr { 2708 unsafe fn from_raw(addr: *const libc::sockaddr, 2709 len: Option<libc::socklen_t>) 2710 -> Option<Self> where Self: Sized 2711 { 2712 if let Some(l) = len { 2713 if l != mem::size_of::<libc::sockaddr_ll>() as libc::socklen_t { 2714 return None; 2715 } 2716 } 2717 if (*addr).sa_family as i32 != libc::AF_PACKET { 2718 return None; 2719 } 2720 Some(Self(ptr::read_unaligned(addr as *const _))) 2721 } 2722 } 2723 2724 impl AsRef<libc::sockaddr_ll> for LinkAddr { 2725 fn as_ref(&self) -> &libc::sockaddr_ll { 2726 &self.0 2727 } 2728 } 2729 2730 } 2731} 2732 2733#[cfg(any( 2734 target_os = "dragonfly", 2735 target_os = "freebsd", 2736 target_os = "ios", 2737 target_os = "macos", 2738 target_os = "illumos", 2739 target_os = "netbsd", 2740 target_os = "haiku", 2741 target_os = "openbsd" 2742))] 2743#[cfg_attr(docsrs, doc(cfg(all())))] 2744mod datalink { 2745 feature! { 2746 #![feature = "net"] 2747 use super::{fmt, mem, private, ptr, SockaddrLike}; 2748 2749 /// Hardware Address 2750 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 2751 #[repr(transparent)] 2752 pub struct LinkAddr(pub(in super::super) libc::sockaddr_dl); 2753 2754 impl LinkAddr { 2755 /// interface index, if != 0, system given index for interface 2756 #[cfg(not(target_os = "haiku"))] 2757 pub fn ifindex(&self) -> usize { 2758 self.0.sdl_index as usize 2759 } 2760 2761 /// Datalink type 2762 #[cfg(not(target_os = "haiku"))] 2763 pub fn datalink_type(&self) -> u8 { 2764 self.0.sdl_type 2765 } 2766 2767 /// MAC address start position 2768 pub fn nlen(&self) -> usize { 2769 self.0.sdl_nlen as usize 2770 } 2771 2772 /// link level address length 2773 pub fn alen(&self) -> usize { 2774 self.0.sdl_alen as usize 2775 } 2776 2777 /// link layer selector length 2778 #[cfg(not(target_os = "haiku"))] 2779 pub fn slen(&self) -> usize { 2780 self.0.sdl_slen as usize 2781 } 2782 2783 /// if link level address length == 0, 2784 /// or `sdl_data` not be larger. 2785 pub fn is_empty(&self) -> bool { 2786 let nlen = self.nlen(); 2787 let alen = self.alen(); 2788 let data_len = self.0.sdl_data.len(); 2789 2790 alen == 0 || nlen + alen >= data_len 2791 } 2792 2793 /// Physical-layer address (MAC) 2794 // The cast is not unnecessary on all platforms. 2795 #[allow(clippy::unnecessary_cast)] 2796 pub fn addr(&self) -> Option<[u8; 6]> { 2797 let nlen = self.nlen(); 2798 let data = self.0.sdl_data; 2799 2800 if self.is_empty() { 2801 None 2802 } else { 2803 Some([ 2804 data[nlen] as u8, 2805 data[nlen + 1] as u8, 2806 data[nlen + 2] as u8, 2807 data[nlen + 3] as u8, 2808 data[nlen + 4] as u8, 2809 data[nlen + 5] as u8, 2810 ]) 2811 } 2812 } 2813 } 2814 2815 impl fmt::Display for LinkAddr { 2816 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 2817 if let Some(addr) = self.addr() { 2818 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", 2819 addr[0], 2820 addr[1], 2821 addr[2], 2822 addr[3], 2823 addr[4], 2824 addr[5]) 2825 } else { 2826 Ok(()) 2827 } 2828 } 2829 } 2830 impl private::SockaddrLikePriv for LinkAddr {} 2831 impl SockaddrLike for LinkAddr { 2832 unsafe fn from_raw(addr: *const libc::sockaddr, 2833 len: Option<libc::socklen_t>) 2834 -> Option<Self> where Self: Sized 2835 { 2836 if let Some(l) = len { 2837 if l != mem::size_of::<libc::sockaddr_dl>() as libc::socklen_t { 2838 return None; 2839 } 2840 } 2841 if (*addr).sa_family as i32 != libc::AF_LINK { 2842 return None; 2843 } 2844 Some(Self(ptr::read_unaligned(addr as *const _))) 2845 } 2846 } 2847 2848 impl AsRef<libc::sockaddr_dl> for LinkAddr { 2849 fn as_ref(&self) -> &libc::sockaddr_dl { 2850 &self.0 2851 } 2852 } 2853 2854 } 2855} 2856 2857#[cfg(any(target_os = "android", target_os = "linux"))] 2858#[cfg_attr(docsrs, doc(cfg(all())))] 2859pub mod vsock { 2860 use super::*; 2861 use crate::sys::socket::addr::AddressFamily; 2862 use libc::{sa_family_t, sockaddr_vm}; 2863 use std::hash::{Hash, Hasher}; 2864 use std::{fmt, mem}; 2865 2866 /// Socket address for VMWare VSockets protocol 2867 /// 2868 /// # References 2869 /// 2870 /// [vsock(7)](https://man7.org/linux/man-pages/man7/vsock.7.html) 2871 #[derive(Copy, Clone)] 2872 #[repr(transparent)] 2873 pub struct VsockAddr(pub(in super::super) sockaddr_vm); 2874 2875 impl private::SockaddrLikePriv for VsockAddr {} 2876 impl SockaddrLike for VsockAddr { 2877 unsafe fn from_raw( 2878 addr: *const libc::sockaddr, 2879 len: Option<libc::socklen_t>, 2880 ) -> Option<Self> 2881 where 2882 Self: Sized, 2883 { 2884 if let Some(l) = len { 2885 if l != mem::size_of::<libc::sockaddr_vm>() as libc::socklen_t { 2886 return None; 2887 } 2888 } 2889 if (*addr).sa_family as i32 != libc::AF_VSOCK { 2890 return None; 2891 } 2892 Some(Self(ptr::read_unaligned(addr as *const _))) 2893 } 2894 } 2895 2896 impl AsRef<libc::sockaddr_vm> for VsockAddr { 2897 fn as_ref(&self) -> &libc::sockaddr_vm { 2898 &self.0 2899 } 2900 } 2901 2902 impl PartialEq for VsockAddr { 2903 fn eq(&self, other: &Self) -> bool { 2904 let (inner, other) = (self.0, other.0); 2905 (inner.svm_family, inner.svm_cid, inner.svm_port) 2906 == (other.svm_family, other.svm_cid, other.svm_port) 2907 } 2908 } 2909 2910 impl Eq for VsockAddr {} 2911 2912 impl Hash for VsockAddr { 2913 fn hash<H: Hasher>(&self, s: &mut H) { 2914 let inner = self.0; 2915 (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s); 2916 } 2917 } 2918 2919 /// VSOCK Address 2920 /// 2921 /// The address for AF_VSOCK socket is defined as a combination of a 2922 /// 32-bit Context Identifier (CID) and a 32-bit port number. 2923 impl VsockAddr { 2924 /// Construct a `VsockAddr` from its raw fields. 2925 pub fn new(cid: u32, port: u32) -> VsockAddr { 2926 let mut addr: sockaddr_vm = unsafe { mem::zeroed() }; 2927 addr.svm_family = AddressFamily::Vsock as sa_family_t; 2928 addr.svm_cid = cid; 2929 addr.svm_port = port; 2930 2931 VsockAddr(addr) 2932 } 2933 2934 /// Context Identifier (CID) 2935 pub fn cid(&self) -> u32 { 2936 self.0.svm_cid 2937 } 2938 2939 /// Port number 2940 pub fn port(&self) -> u32 { 2941 self.0.svm_port 2942 } 2943 } 2944 2945 impl fmt::Display for VsockAddr { 2946 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 2947 write!(f, "cid: {} port: {}", self.cid(), self.port()) 2948 } 2949 } 2950 2951 impl fmt::Debug for VsockAddr { 2952 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 2953 fmt::Display::fmt(self, f) 2954 } 2955 } 2956} 2957 2958#[cfg(test)] 2959mod tests { 2960 use super::*; 2961 2962 mod types { 2963 use super::*; 2964 2965 #[test] 2966 fn test_ipv4addr_to_libc() { 2967 let s = std::net::Ipv4Addr::new(1, 2, 3, 4); 2968 let l = ipv4addr_to_libc(s); 2969 assert_eq!(l.s_addr, u32::to_be(0x01020304)); 2970 } 2971 2972 #[test] 2973 fn test_ipv6addr_to_libc() { 2974 let s = std::net::Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8); 2975 let l = ipv6addr_to_libc(&s); 2976 assert_eq!( 2977 l.s6_addr, 2978 [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8] 2979 ); 2980 } 2981 } 2982 2983 mod link { 2984 #![allow(clippy::cast_ptr_alignment)] 2985 2986 #[cfg(any( 2987 target_os = "ios", 2988 target_os = "macos", 2989 target_os = "illumos" 2990 ))] 2991 use super::super::super::socklen_t; 2992 use super::*; 2993 2994 /// Don't panic when trying to display an empty datalink address 2995 #[cfg(any( 2996 target_os = "dragonfly", 2997 target_os = "freebsd", 2998 target_os = "ios", 2999 target_os = "macos", 3000 target_os = "netbsd", 3001 target_os = "openbsd" 3002 ))] 3003 #[test] 3004 fn test_datalink_display() { 3005 use super::super::LinkAddr; 3006 use std::mem; 3007 3008 let la = LinkAddr(libc::sockaddr_dl { 3009 sdl_len: 56, 3010 sdl_family: 18, 3011 sdl_index: 5, 3012 sdl_type: 24, 3013 sdl_nlen: 3, 3014 sdl_alen: 0, 3015 sdl_slen: 0, 3016 ..unsafe { mem::zeroed() } 3017 }); 3018 format!("{}", la); 3019 } 3020 3021 #[cfg(all( 3022 any( 3023 target_os = "android", 3024 target_os = "fuchsia", 3025 target_os = "linux" 3026 ), 3027 target_endian = "little" 3028 ))] 3029 #[test] 3030 fn linux_loopback() { 3031 #[repr(align(2))] 3032 struct Raw([u8; 20]); 3033 3034 let bytes = Raw([ 3035 17u8, 0, 0, 0, 1, 0, 0, 0, 4, 3, 0, 6, 1, 2, 3, 4, 5, 6, 0, 0, 3036 ]); 3037 let sa = bytes.0.as_ptr() as *const libc::sockaddr; 3038 let len = None; 3039 let sock_addr = 3040 unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap(); 3041 assert_eq!(sock_addr.family(), Some(AddressFamily::Packet)); 3042 match sock_addr.as_link_addr() { 3043 Some(dl) => assert_eq!(dl.addr(), Some([1, 2, 3, 4, 5, 6])), 3044 None => panic!("Can't unwrap sockaddr storage"), 3045 } 3046 } 3047 3048 #[cfg(any(target_os = "ios", target_os = "macos"))] 3049 #[test] 3050 fn macos_loopback() { 3051 let bytes = 3052 [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0]; 3053 let sa = bytes.as_ptr() as *const libc::sockaddr; 3054 let len = Some(bytes.len() as socklen_t); 3055 let sock_addr = 3056 unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap(); 3057 assert_eq!(sock_addr.family(), Some(AddressFamily::Link)); 3058 match sock_addr.as_link_addr() { 3059 Some(dl) => { 3060 assert!(dl.addr().is_none()); 3061 } 3062 None => panic!("Can't unwrap sockaddr storage"), 3063 } 3064 } 3065 3066 #[cfg(any(target_os = "ios", target_os = "macos"))] 3067 #[test] 3068 fn macos_tap() { 3069 let bytes = [ 3070 20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35, 3071 76, -80, 3072 ]; 3073 let ptr = bytes.as_ptr(); 3074 let sa = ptr as *const libc::sockaddr; 3075 let len = Some(bytes.len() as socklen_t); 3076 3077 let sock_addr = 3078 unsafe { SockaddrStorage::from_raw(sa, len).unwrap() }; 3079 assert_eq!(sock_addr.family(), Some(AddressFamily::Link)); 3080 match sock_addr.as_link_addr() { 3081 Some(dl) => { 3082 assert_eq!(dl.addr(), Some([24u8, 101, 144, 221, 76, 176])) 3083 } 3084 None => panic!("Can't unwrap sockaddr storage"), 3085 } 3086 } 3087 3088 #[cfg(target_os = "illumos")] 3089 #[test] 3090 fn illumos_tap() { 3091 let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176]; 3092 let ptr = bytes.as_ptr(); 3093 let sa = ptr as *const libc::sockaddr; 3094 let len = Some(bytes.len() as socklen_t); 3095 let _sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) }; 3096 3097 assert!(_sock_addr.is_some()); 3098 3099 let sock_addr = _sock_addr.unwrap(); 3100 3101 assert_eq!(sock_addr.family().unwrap(), AddressFamily::Link); 3102 3103 assert_eq!( 3104 sock_addr.as_link_addr().unwrap().addr(), 3105 Some([24u8, 101, 144, 221, 76, 176]) 3106 ); 3107 } 3108 3109 #[test] 3110 fn size() { 3111 #[cfg(any( 3112 target_os = "dragonfly", 3113 target_os = "freebsd", 3114 target_os = "ios", 3115 target_os = "macos", 3116 target_os = "netbsd", 3117 target_os = "illumos", 3118 target_os = "openbsd", 3119 target_os = "haiku" 3120 ))] 3121 let l = mem::size_of::<libc::sockaddr_dl>(); 3122 #[cfg(any( 3123 target_os = "android", 3124 target_os = "fuchsia", 3125 target_os = "linux" 3126 ))] 3127 let l = mem::size_of::<libc::sockaddr_ll>(); 3128 assert_eq!(LinkAddr::size() as usize, l); 3129 } 3130 } 3131 3132 mod sockaddr_in { 3133 use super::*; 3134 use std::str::FromStr; 3135 3136 #[test] 3137 fn display() { 3138 let s = "127.0.0.1:8080"; 3139 let addr = SockaddrIn::from_str(s).unwrap(); 3140 assert_eq!(s, format!("{}", addr)); 3141 } 3142 3143 #[test] 3144 fn size() { 3145 assert_eq!( 3146 mem::size_of::<libc::sockaddr_in>(), 3147 SockaddrIn::size() as usize 3148 ); 3149 } 3150 } 3151 3152 mod sockaddr_in6 { 3153 use super::*; 3154 use std::str::FromStr; 3155 3156 #[test] 3157 fn display() { 3158 let s = "[1234:5678:90ab:cdef::1111:2222]:8080"; 3159 let addr = SockaddrIn6::from_str(s).unwrap(); 3160 assert_eq!(s, format!("{}", addr)); 3161 } 3162 3163 #[test] 3164 fn size() { 3165 assert_eq!( 3166 mem::size_of::<libc::sockaddr_in6>(), 3167 SockaddrIn6::size() as usize 3168 ); 3169 } 3170 3171 #[test] 3172 // Ensure that we can convert to-and-from std::net variants without change. 3173 fn to_and_from() { 3174 let s = "[1234:5678:90ab:cdef::1111:2222]:8080"; 3175 let mut nix_sin6 = SockaddrIn6::from_str(s).unwrap(); 3176 nix_sin6.0.sin6_flowinfo = 0x12345678; 3177 nix_sin6.0.sin6_scope_id = 0x9abcdef0; 3178 3179 let std_sin6 : std::net::SocketAddrV6 = nix_sin6.into(); 3180 assert_eq!(nix_sin6, std_sin6.into()); 3181 } 3182 } 3183 3184 mod sockaddr_storage { 3185 use super::*; 3186 3187 #[test] 3188 fn from_sockaddr_un_named() { 3189 let ua = UnixAddr::new("/var/run/mysock").unwrap(); 3190 let ptr = ua.as_ptr() as *const libc::sockaddr; 3191 let ss = unsafe { 3192 SockaddrStorage::from_raw(ptr, Some(ua.len())) 3193 }.unwrap(); 3194 assert_eq!(ss.len(), ua.len()); 3195 } 3196 3197 #[cfg(any(target_os = "android", target_os = "linux"))] 3198 #[test] 3199 fn from_sockaddr_un_abstract_named() { 3200 let name = String::from("nix\0abstract\0test"); 3201 let ua = UnixAddr::new_abstract(name.as_bytes()).unwrap(); 3202 let ptr = ua.as_ptr() as *const libc::sockaddr; 3203 let ss = unsafe { 3204 SockaddrStorage::from_raw(ptr, Some(ua.len())) 3205 }.unwrap(); 3206 assert_eq!(ss.len(), ua.len()); 3207 } 3208 3209 #[cfg(any(target_os = "android", target_os = "linux"))] 3210 #[test] 3211 fn from_sockaddr_un_abstract_unnamed() { 3212 let ua = UnixAddr::new_unnamed(); 3213 let ptr = ua.as_ptr() as *const libc::sockaddr; 3214 let ss = unsafe { 3215 SockaddrStorage::from_raw(ptr, Some(ua.len())) 3216 }.unwrap(); 3217 assert_eq!(ss.len(), ua.len()); 3218 } 3219 } 3220 3221 mod unixaddr { 3222 use super::*; 3223 3224 #[cfg(any(target_os = "android", target_os = "linux"))] 3225 #[test] 3226 fn abstract_sun_path() { 3227 let name = String::from("nix\0abstract\0test"); 3228 let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap(); 3229 3230 let sun_path1 = 3231 unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] }; 3232 let sun_path2 = [ 3233 0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 3234 116, 101, 115, 116, 3235 ]; 3236 assert_eq!(sun_path1, sun_path2); 3237 } 3238 3239 #[test] 3240 fn size() { 3241 assert_eq!( 3242 mem::size_of::<libc::sockaddr_un>(), 3243 UnixAddr::size() as usize 3244 ); 3245 } 3246 } 3247} 3248