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#[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 unsafe {
48 mem::transmute(addr)
49 }
50}
51
52#[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 unsafe {
58 mem::transmute(*addr)
59 }
60}
61
62#[repr(i32)]
70#[non_exhaustive]
71#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
72pub enum AddressFamily {
73 Unix = libc::AF_UNIX,
75 Inet = libc::AF_INET,
77 Inet6 = libc::AF_INET6,
79 #[cfg(any(target_os = "android", target_os = "linux"))]
81 #[cfg_attr(docsrs, doc(cfg(all())))]
82 Netlink = libc::AF_NETLINK,
83 #[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 #[cfg(any(target_os = "ios", target_os = "macos"))]
95 #[cfg_attr(docsrs, doc(cfg(all())))]
96 System = libc::AF_SYSTEM,
97 #[cfg(any(target_os = "android", target_os = "linux"))]
99 #[cfg_attr(docsrs, doc(cfg(all())))]
100 Ax25 = libc::AF_AX25,
101 Ipx = libc::AF_IPX,
103 AppleTalk = libc::AF_APPLETALK,
105 #[cfg(any(target_os = "android", target_os = "linux"))]
108 #[cfg_attr(docsrs, doc(cfg(all())))]
109 NetRom = libc::AF_NETROM,
110 #[cfg(any(target_os = "android", target_os = "linux"))]
115 #[cfg_attr(docsrs, doc(cfg(all())))]
116 Bridge = libc::AF_BRIDGE,
117 #[cfg(any(target_os = "android", target_os = "linux"))]
119 #[cfg_attr(docsrs, doc(cfg(all())))]
120 AtmPvc = libc::AF_ATMPVC,
121 #[cfg(any(target_os = "android", target_os = "linux"))]
123 #[cfg_attr(docsrs, doc(cfg(all())))]
124 X25 = libc::AF_X25,
125 #[cfg(any(target_os = "android", target_os = "linux"))]
129 #[cfg_attr(docsrs, doc(cfg(all())))]
130 Rose = libc::AF_ROSE,
131 #[cfg(not(target_os = "haiku"))]
133 Decnet = libc::AF_DECnet,
134 #[cfg(any(target_os = "android", target_os = "linux"))]
136 #[cfg_attr(docsrs, doc(cfg(all())))]
137 NetBeui = libc::AF_NETBEUI,
138 #[cfg(any(target_os = "android", target_os = "linux"))]
141 #[cfg_attr(docsrs, doc(cfg(all())))]
142 Security = libc::AF_SECURITY,
143 #[cfg(any(target_os = "android", target_os = "linux"))]
145 #[cfg_attr(docsrs, doc(cfg(all())))]
146 Key = libc::AF_KEY,
147 #[allow(missing_docs)] #[cfg(any(target_os = "android", target_os = "linux"))]
149 #[cfg_attr(docsrs, doc(cfg(all())))]
150 Ash = libc::AF_ASH,
151 #[cfg(any(target_os = "android", target_os = "linux"))]
153 #[cfg_attr(docsrs, doc(cfg(all())))]
154 Econet = libc::AF_ECONET,
155 #[cfg(any(target_os = "android", target_os = "linux"))]
157 #[cfg_attr(docsrs, doc(cfg(all())))]
158 AtmSvc = libc::AF_ATMSVC,
159 #[cfg(any(target_os = "android", target_os = "linux"))]
161 #[cfg_attr(docsrs, doc(cfg(all())))]
162 Rds = libc::AF_RDS,
163 #[cfg(not(target_os = "haiku"))]
165 Sna = libc::AF_SNA,
166 #[cfg(any(target_os = "android", target_os = "linux"))]
168 #[cfg_attr(docsrs, doc(cfg(all())))]
169 Irda = libc::AF_IRDA,
170 #[cfg(any(target_os = "android", target_os = "linux"))]
172 #[cfg_attr(docsrs, doc(cfg(all())))]
173 Pppox = libc::AF_PPPOX,
174 #[cfg(any(target_os = "android", target_os = "linux"))]
177 #[cfg_attr(docsrs, doc(cfg(all())))]
178 Wanpipe = libc::AF_WANPIPE,
179 #[cfg(any(target_os = "android", target_os = "linux"))]
181 #[cfg_attr(docsrs, doc(cfg(all())))]
182 Llc = libc::AF_LLC,
183 #[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
185 #[cfg_attr(docsrs, doc(cfg(all())))]
186 Ib = libc::AF_IB,
187 #[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
189 #[cfg_attr(docsrs, doc(cfg(all())))]
190 Mpls = libc::AF_MPLS,
191 #[cfg(any(target_os = "android", target_os = "linux"))]
193 #[cfg_attr(docsrs, doc(cfg(all())))]
194 Can = libc::AF_CAN,
195 #[cfg(any(target_os = "android", target_os = "linux"))]
197 #[cfg_attr(docsrs, doc(cfg(all())))]
198 Tipc = libc::AF_TIPC,
199 #[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 #[cfg(any(target_os = "android", target_os = "linux"))]
211 #[cfg_attr(docsrs, doc(cfg(all())))]
212 Iucv = libc::AF_IUCV,
213 #[cfg(any(target_os = "android", target_os = "linux"))]
215 #[cfg_attr(docsrs, doc(cfg(all())))]
216 RxRpc = libc::AF_RXRPC,
217 #[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 #[cfg(any(target_os = "android", target_os = "linux"))]
227 #[cfg_attr(docsrs, doc(cfg(all())))]
228 Phonet = libc::AF_PHONET,
229 #[cfg(any(target_os = "android", target_os = "linux"))]
231 #[cfg_attr(docsrs, doc(cfg(all())))]
232 Ieee802154 = libc::AF_IEEE802154,
233 #[cfg(any(target_os = "android", target_os = "linux"))]
236 #[cfg_attr(docsrs, doc(cfg(all())))]
237 Caif = libc::AF_CAIF,
238 #[cfg(any(target_os = "android", target_os = "linux"))]
240 #[cfg_attr(docsrs, doc(cfg(all())))]
241 Alg = libc::AF_ALG,
242 #[cfg(target_os = "linux")]
244 #[cfg_attr(docsrs, doc(cfg(all())))]
245 Nfc = libc::AF_NFC,
246 #[cfg(any(target_os = "android", target_os = "linux"))]
248 #[cfg_attr(docsrs, doc(cfg(all())))]
249 Vsock = libc::AF_VSOCK,
250 #[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 #[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 #[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 #[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)] #[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 #[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 #[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 #[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)] #[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 #[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 #[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 #[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 #[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 #[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 #[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 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)] #[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)] #[allow(deprecated)]
459impl InetAddr {
460 #[allow(clippy::needless_update)] 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(), 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(), sin6_addr: Ipv6Addr::from_std(addr.ip()).0,
486 sin6_flowinfo: addr.flowinfo(), sin6_scope_id: addr.scope_id(), .. unsafe { mem::zeroed() }
489 })
490 }
491 }
492 }
493
494 #[allow(clippy::needless_update)] 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 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 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#[allow(missing_docs)] #[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)] impl IpAddr {
582 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 #[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#[deprecated(
630 since = "0.24.0",
631 note = "Use std::net::Ipv4Addr instead"
632)]
633#[allow(missing_docs)] #[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)] impl Ipv4Addr {
641 #[allow(clippy::identity_op)] 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 #[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#[deprecated(
688 since = "0.24.0",
689 note = "Use std::net::Ipv6Addr instead"
690)]
691#[allow(missing_docs)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
693#[repr(transparent)]
694pub struct Ipv6Addr(pub libc::in6_addr);
695
696macro_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)] impl 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 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#[derive(Clone, Copy, Debug)]
747#[repr(C)]
748pub struct UnixAddr {
749 sun: libc::sockaddr_un,
751 #[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#[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 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 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 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 #[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 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 #[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 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 unsafe { UnixAddrKind::get(&self.sun, self.sun_len()) }
935 }
936
937 pub fn path(&self) -> Option<&Path> {
939 match self.kind() {
940 UnixAddrKind::Pathname(path) => Some(path),
941 _ => None,
942 }
943 }
944
945 #[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 #[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 #[inline]
968 pub fn path_len(&self) -> usize {
969 self.sun_len() as usize - offset_of!(libc::sockaddr_un, sun_path)
970 }
971 #[inline]
973 pub fn as_ptr(&self) -> *const libc::sockaddr_un {
974 &self.sun
975 }
976 #[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#[allow(clippy::len_without_is_empty)]
1102pub trait SockaddrLike: private::SockaddrLikePriv {
1103 fn as_ptr(&self) -> *const libc::sockaddr {
1105 self as *const Self as *const libc::sockaddr
1106 }
1107
1108 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 fn family(&self) -> Option<AddressFamily> {
1152 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 fn len(&self) -> libc::socklen_t {
1172 unsafe {
1176 (*(self as *const Self as *const libc::sockaddr)).sa_len
1177 }.into()
1178 }
1179 } else {
1180 fn len(&self) -> libc::socklen_t {
1186 mem::size_of_val(self) as libc::socklen_t
1190 }
1191 }
1192 }
1193
1194 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
1209impl 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#[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 pub const fn ip(&self) -> libc::in_addr_t {
1251 u32::from_be(self.0.sin_addr.s_addr)
1252 }
1253
1254 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 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(), 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#[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 pub const fn flowinfo(&self) -> u32 {
1382 self.0.sin6_flowinfo
1383 }
1384
1385 pub fn ip(&self) -> net::Ipv6Addr {
1387 net::Ipv6Addr::from(self.0.sin6_addr.s6_addr)
1388 }
1389
1390 pub const fn port(&self) -> u16 {
1393 u16::from_be(self.0.sin6_port)
1394 }
1395
1396 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 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)] 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(), sin6_addr: ipv6addr_to_libc(addr.ip()),
1466 sin6_flowinfo: addr.flowinfo(), sin6_scope_id: addr.scope_id(), ..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 u32::from_be(addr.0.sin6_flowinfo),
1480 u32::from_be(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#[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 (*(&mut ss as *mut libc::sockaddr_storage as *mut UnixAddr)).sun_len = len as u8;
1571 }
1572 Some(Self { ss })
1573 }
1574 } else {
1575 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 Some(ua) => ua.len(),
1644 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 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 Some(unsafe { &self.$field })
1665 } else {
1666 None
1667 }
1668 }
1669
1670 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 Some(unsafe { &mut self.$field })
1677 } else {
1678 None
1679 }
1680 }
1681 };
1682}
1683
1684impl SockaddrStorage {
1685 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 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 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 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 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 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 .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 fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
1975 self as *mut Self as *mut libc::sockaddr
1976 }
1977 }
1978}
1979
1980#[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)] #[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 #[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)] #[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 #[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 Some(_) | None => None,
2175 }
2176 }
2177 }
2178
2179 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 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 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 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 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 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 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 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 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 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 #[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 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 pub const fn pid(&self) -> u32 {
2363 self.0.nl_pid
2364 }
2365
2366 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 #[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 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 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 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 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 #[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 #[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 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 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 pub const fn id(&self) -> u32 {
2622 self.0.sc_id
2623 }
2624
2625 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 #[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 pub fn protocol(&self) -> u16 {
2654 self.0.sll_protocol
2655 }
2656
2657 pub fn ifindex(&self) -> usize {
2659 self.0.sll_ifindex as usize
2660 }
2661
2662 pub fn hatype(&self) -> u16 {
2664 self.0.sll_hatype
2665 }
2666
2667 pub fn pkttype(&self) -> u8 {
2669 self.0.sll_pkttype
2670 }
2671
2672 pub fn halen(&self) -> usize {
2674 self.0.sll_halen as usize
2675 }
2676
2677 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 #[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 #[cfg(not(target_os = "haiku"))]
2757 pub fn ifindex(&self) -> usize {
2758 self.0.sdl_index as usize
2759 }
2760
2761 #[cfg(not(target_os = "haiku"))]
2763 pub fn datalink_type(&self) -> u8 {
2764 self.0.sdl_type
2765 }
2766
2767 pub fn nlen(&self) -> usize {
2769 self.0.sdl_nlen as usize
2770 }
2771
2772 pub fn alen(&self) -> usize {
2774 self.0.sdl_alen as usize
2775 }
2776
2777 #[cfg(not(target_os = "haiku"))]
2779 pub fn slen(&self) -> usize {
2780 self.0.sdl_slen as usize
2781 }
2782
2783 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 #[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 #[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 impl VsockAddr {
2924 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 pub fn cid(&self) -> u32 {
2936 self.0.svm_cid
2937 }
2938
2939 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 #[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
3172 mod sockaddr_storage {
3173 use super::*;
3174
3175 #[test]
3176 fn from_sockaddr_un_named() {
3177 let ua = UnixAddr::new("/var/run/mysock").unwrap();
3178 let ptr = ua.as_ptr() as *const libc::sockaddr;
3179 let ss = unsafe {
3180 SockaddrStorage::from_raw(ptr, Some(ua.len()))
3181 }.unwrap();
3182 assert_eq!(ss.len(), ua.len());
3183 }
3184
3185 #[cfg(any(target_os = "android", target_os = "linux"))]
3186 #[test]
3187 fn from_sockaddr_un_abstract_named() {
3188 let name = String::from("nix\0abstract\0test");
3189 let ua = UnixAddr::new_abstract(name.as_bytes()).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_unnamed() {
3200 let ua = UnixAddr::new_unnamed();
3201 let ptr = ua.as_ptr() as *const libc::sockaddr;
3202 let ss = unsafe {
3203 SockaddrStorage::from_raw(ptr, Some(ua.len()))
3204 }.unwrap();
3205 assert_eq!(ss.len(), ua.len());
3206 }
3207 }
3208
3209 mod unixaddr {
3210 use super::*;
3211
3212 #[cfg(any(target_os = "android", target_os = "linux"))]
3213 #[test]
3214 fn abstract_sun_path() {
3215 let name = String::from("nix\0abstract\0test");
3216 let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
3217
3218 let sun_path1 =
3219 unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] };
3220 let sun_path2 = [
3221 0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0,
3222 116, 101, 115, 116,
3223 ];
3224 assert_eq!(sun_path1, sun_path2);
3225 }
3226
3227 #[test]
3228 fn size() {
3229 assert_eq!(
3230 mem::size_of::<libc::sockaddr_un>(),
3231 UnixAddr::size() as usize
3232 );
3233 }
3234 }
3235}