1#[cfg(any(
2 bsd,
3 linux_android,
4 solarish,
5 target_os = "haiku",
6 target_os = "fuchsia",
7 target_os = "aix",
8))]
9#[cfg(feature = "net")]
10pub use self::datalink::LinkAddr;
11#[cfg(any(linux_android, apple_targets))]
12pub use self::vsock::VsockAddr;
13use super::sa_family_t;
14use crate::errno::Errno;
15#[cfg(linux_android)]
16use crate::sys::socket::addr::alg::AlgAddr;
17#[cfg(linux_android)]
18use crate::sys::socket::addr::netlink::NetlinkAddr;
19#[cfg(all(feature = "ioctl", apple_targets))]
20use crate::sys::socket::addr::sys_control::SysControlAddr;
21use crate::{NixPath, Result};
22use cfg_if::cfg_if;
23use memoffset::offset_of;
24use std::convert::TryInto;
25use std::ffi::OsStr;
26use std::hash::{Hash, Hasher};
27use std::net::{Ipv4Addr, Ipv6Addr};
28use std::os::unix::ffi::OsStrExt;
29use std::path::Path;
30use std::{fmt, mem, net, ptr, slice};
31
32#[cfg(feature = "net")]
34pub(crate) const fn ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr {
35 libc::in_addr {
36 s_addr: u32::from_ne_bytes(addr.octets()),
37 }
38}
39
40#[cfg(feature = "net")]
42pub(crate) const fn ipv6addr_to_libc(addr: &net::Ipv6Addr) -> libc::in6_addr {
43 libc::in6_addr {
44 s6_addr: addr.octets(),
45 }
46}
47
48#[repr(i32)]
56#[non_exhaustive]
57#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
58pub enum AddressFamily {
59 Unix = libc::AF_UNIX,
61 Inet = libc::AF_INET,
63 Inet6 = libc::AF_INET6,
65 #[cfg(linux_android)]
67 Netlink = libc::AF_NETLINK,
68 #[cfg(not(any(linux_android, target_os = "redox")))]
70 Route = libc::PF_ROUTE,
71 #[cfg(any(linux_android, solarish, target_os = "fuchsia"))]
73 Packet = libc::AF_PACKET,
74 #[cfg(apple_targets)]
76 System = libc::AF_SYSTEM,
77 #[cfg(linux_android)]
79 Ax25 = libc::AF_AX25,
80 #[cfg(not(any(target_os = "aix", target_os = "redox")))]
82 Ipx = libc::AF_IPX,
83 #[cfg(not(target_os = "redox"))]
85 AppleTalk = libc::AF_APPLETALK,
86 #[cfg(linux_android)]
89 NetRom = libc::AF_NETROM,
90 #[cfg(linux_android)]
95 Bridge = libc::AF_BRIDGE,
96 #[cfg(linux_android)]
98 AtmPvc = libc::AF_ATMPVC,
99 #[cfg(linux_android)]
101 X25 = libc::AF_X25,
102 #[cfg(linux_android)]
106 Rose = libc::AF_ROSE,
107 #[cfg(not(any(target_os = "haiku", target_os = "redox")))]
109 Decnet = libc::AF_DECnet,
110 #[cfg(linux_android)]
112 NetBeui = libc::AF_NETBEUI,
113 #[cfg(linux_android)]
116 Security = libc::AF_SECURITY,
117 #[cfg(linux_android)]
119 Key = libc::AF_KEY,
120 #[allow(missing_docs)] #[cfg(linux_android)]
122 Ash = libc::AF_ASH,
123 #[cfg(linux_android)]
125 Econet = libc::AF_ECONET,
126 #[cfg(linux_android)]
128 AtmSvc = libc::AF_ATMSVC,
129 #[cfg(linux_android)]
131 Rds = libc::AF_RDS,
132 #[cfg(not(any(target_os = "haiku", target_os = "redox")))]
134 Sna = libc::AF_SNA,
135 #[cfg(linux_android)]
137 Irda = libc::AF_IRDA,
138 #[cfg(linux_android)]
140 Pppox = libc::AF_PPPOX,
141 #[cfg(linux_android)]
144 Wanpipe = libc::AF_WANPIPE,
145 #[cfg(linux_android)]
147 Llc = libc::AF_LLC,
148 #[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
150 Ib = libc::AF_IB,
151 #[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
153 Mpls = libc::AF_MPLS,
154 #[cfg(linux_android)]
156 Can = libc::AF_CAN,
157 #[cfg(linux_android)]
159 Tipc = libc::AF_TIPC,
160 #[cfg(not(any(
162 target_os = "aix",
163 solarish,
164 apple_targets,
165 target_os = "hurd",
166 target_os = "redox",
167 )))]
168 Bluetooth = libc::AF_BLUETOOTH,
169 #[cfg(linux_android)]
172 Iucv = libc::AF_IUCV,
173 #[cfg(linux_android)]
175 RxRpc = libc::AF_RXRPC,
176 #[cfg(not(any(
178 target_os = "aix",
179 solarish,
180 target_os = "haiku",
181 target_os = "hurd",
182 target_os = "redox",
183 )))]
184 Isdn = libc::AF_ISDN,
185 #[cfg(linux_android)]
187 Phonet = libc::AF_PHONET,
188 #[cfg(linux_android)]
190 Ieee802154 = libc::AF_IEEE802154,
191 #[cfg(linux_android)]
194 Caif = libc::AF_CAIF,
195 #[cfg(linux_android)]
197 Alg = libc::AF_ALG,
198 #[cfg(target_os = "linux")]
200 Nfc = libc::AF_NFC,
201 #[cfg(any(linux_android, apple_targets))]
203 Vsock = libc::AF_VSOCK,
204 #[cfg(bsd)]
206 ImpLink = libc::AF_IMPLINK,
207 #[cfg(bsd)]
209 Pup = libc::AF_PUP,
210 #[cfg(bsd)]
212 Chaos = libc::AF_CHAOS,
213 #[cfg(any(apple_targets, netbsdlike))]
215 Ns = libc::AF_NS,
216 #[allow(missing_docs)] #[cfg(bsd)]
218 Iso = libc::AF_ISO,
219 #[cfg(bsd)]
221 Datakit = libc::AF_DATAKIT,
222 #[cfg(bsd)]
224 Ccitt = libc::AF_CCITT,
225 #[cfg(bsd)]
227 Dli = libc::AF_DLI,
228 #[allow(missing_docs)] #[cfg(bsd)]
230 Lat = libc::AF_LAT,
231 #[cfg(bsd)]
233 Hylink = libc::AF_HYLINK,
234 #[cfg(any(bsd, solarish))]
236 Link = libc::AF_LINK,
237 #[cfg(bsd)]
239 Coip = libc::AF_COIP,
240 #[cfg(bsd)]
242 Cnt = libc::AF_CNT,
243 #[cfg(bsd)]
245 Natm = libc::AF_NATM,
246 #[cfg(linux_android)]
248 Unspec = libc::AF_UNSPEC,
249}
250
251impl AddressFamily {
252 pub const fn from_i32(family: i32) -> Option<AddressFamily> {
258 match family {
259 libc::AF_UNIX => Some(AddressFamily::Unix),
260 libc::AF_INET => Some(AddressFamily::Inet),
261 libc::AF_INET6 => Some(AddressFamily::Inet6),
262 #[cfg(linux_android)]
263 libc::AF_NETLINK => Some(AddressFamily::Netlink),
264 #[cfg(apple_targets)]
265 libc::AF_SYSTEM => Some(AddressFamily::System),
266 #[cfg(not(any(linux_android, target_os = "redox")))]
267 libc::PF_ROUTE => Some(AddressFamily::Route),
268 #[cfg(linux_android)]
269 libc::AF_PACKET => Some(AddressFamily::Packet),
270 #[cfg(any(bsd, solarish))]
271 libc::AF_LINK => Some(AddressFamily::Link),
272 #[cfg(any(linux_android, apple_targets))]
273 libc::AF_VSOCK => Some(AddressFamily::Vsock),
274 _ => None,
275 }
276 }
277}
278
279#[derive(Clone, Copy, Debug)]
281#[repr(C)]
282pub struct UnixAddr {
283 sun: libc::sockaddr_un,
285 #[cfg(not(any(bsd, target_os = "haiku", target_os = "hurd")))]
289 sun_len: u8,
290}
291
292#[derive(PartialEq, Eq, Hash)]
299enum UnixAddrKind<'a> {
300 Pathname(&'a Path),
301 Unnamed,
302 #[cfg(linux_android)]
303 Abstract(&'a [u8]),
304}
305impl<'a> UnixAddrKind<'a> {
306 #[allow(clippy::unnecessary_cast)] unsafe fn get(sun: &'a libc::sockaddr_un, sun_len: u8) -> Self {
309 assert!(sun_len as usize >= offset_of!(libc::sockaddr_un, sun_path));
310 let path_len =
311 sun_len as usize - offset_of!(libc::sockaddr_un, sun_path);
312 if path_len == 0 {
313 return Self::Unnamed;
314 }
315 #[cfg(linux_android)]
316 if sun.sun_path[0] == 0 {
317 let name = unsafe {
318 slice::from_raw_parts(
319 sun.sun_path.as_ptr().add(1).cast(),
320 path_len - 1,
321 )
322 };
323 return Self::Abstract(name);
324 }
325 let pathname = unsafe {
326 slice::from_raw_parts(sun.sun_path.as_ptr().cast(), path_len)
327 };
328 if pathname.last() == Some(&0) {
329 Self::Pathname(Path::new(OsStr::from_bytes(
337 &pathname[0..pathname.len() - 1],
338 )))
339 } else {
340 Self::Pathname(Path::new(OsStr::from_bytes(pathname)))
341 }
342 }
343}
344
345impl UnixAddr {
346 #[allow(clippy::unnecessary_cast)] pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
349 path.with_nix_path(|cstr| unsafe {
350 let mut ret = libc::sockaddr_un {
351 sun_family: AddressFamily::Unix as sa_family_t,
352 ..mem::zeroed()
353 };
354
355 let bytes = cstr.to_bytes();
356
357 if bytes.len() >= ret.sun_path.len() {
358 return Err(Errno::ENAMETOOLONG);
359 }
360
361 let sun_len = (bytes.len()
362 + offset_of!(libc::sockaddr_un, sun_path))
363 .try_into()
364 .unwrap();
365
366 #[cfg(any(bsd, target_os = "haiku", target_os = "hurd"))]
367 {
368 ret.sun_len = sun_len;
369 }
370 ptr::copy_nonoverlapping(
371 bytes.as_ptr(),
372 ret.sun_path.as_mut_ptr().cast(),
373 bytes.len(),
374 );
375
376 Ok(UnixAddr::from_raw_parts(ret, sun_len))
377 })?
378 }
379
380 #[cfg(linux_android)]
387 #[allow(clippy::unnecessary_cast)] pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
389 unsafe {
390 let mut ret = libc::sockaddr_un {
391 sun_family: AddressFamily::Unix as sa_family_t,
392 ..mem::zeroed()
393 };
394
395 if path.len() >= ret.sun_path.len() {
396 return Err(Errno::ENAMETOOLONG);
397 }
398 let sun_len =
399 (path.len() + 1 + offset_of!(libc::sockaddr_un, sun_path))
400 .try_into()
401 .unwrap();
402
403 ptr::copy_nonoverlapping(
406 path.as_ptr(),
407 ret.sun_path.as_mut_ptr().offset(1).cast(),
408 path.len(),
409 );
410
411 Ok(UnixAddr::from_raw_parts(ret, sun_len))
412 }
413 }
414
415 #[cfg(linux_android)]
417 pub fn new_unnamed() -> UnixAddr {
418 let ret = libc::sockaddr_un {
419 sun_family: AddressFamily::Unix as sa_family_t,
420 ..unsafe { mem::zeroed() }
421 };
422
423 let sun_len: u8 =
424 offset_of!(libc::sockaddr_un, sun_path).try_into().unwrap();
425
426 unsafe { UnixAddr::from_raw_parts(ret, sun_len) }
427 }
428
429 pub(crate) unsafe fn from_raw_parts(
441 sun: libc::sockaddr_un,
442 sun_len: u8,
443 ) -> UnixAddr {
444 cfg_if! {
445 if #[cfg(any(linux_android,
446 target_os = "fuchsia",
447 solarish,
448 target_os = "redox",
449 ))]
450 {
451 UnixAddr { sun, sun_len }
452 } else {
453 assert_eq!(sun_len, sun.sun_len);
454 UnixAddr {sun}
455 }
456 }
457 }
458
459 fn kind(&self) -> UnixAddrKind<'_> {
460 unsafe { UnixAddrKind::get(&self.sun, self.sun_len()) }
462 }
463
464 pub fn path(&self) -> Option<&Path> {
466 match self.kind() {
467 UnixAddrKind::Pathname(path) => Some(path),
468 _ => None,
469 }
470 }
471
472 #[cfg(linux_android)]
477 pub fn as_abstract(&self) -> Option<&[u8]> {
478 match self.kind() {
479 UnixAddrKind::Abstract(name) => Some(name),
480 _ => None,
481 }
482 }
483
484 #[cfg(linux_android)]
486 #[inline]
487 pub fn is_unnamed(&self) -> bool {
488 matches!(self.kind(), UnixAddrKind::Unnamed)
489 }
490
491 #[inline]
493 pub fn path_len(&self) -> usize {
494 self.sun_len() as usize - offset_of!(libc::sockaddr_un, sun_path)
495 }
496 #[inline]
498 pub fn as_ptr(&self) -> *const libc::sockaddr_un {
499 &self.sun
500 }
501 #[inline]
503 pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr_un {
504 &mut self.sun
505 }
506
507 fn sun_len(&self) -> u8 {
508 cfg_if! {
509 if #[cfg(any(linux_android,
510 target_os = "fuchsia",
511 solarish,
512 target_os = "redox",
513 ))]
514 {
515 self.sun_len
516 } else {
517 self.sun.sun_len
518 }
519 }
520 }
521}
522
523impl private::SockaddrLikePriv for UnixAddr {}
524impl SockaddrLike for UnixAddr {
525 #[cfg(any(
526 linux_android,
527 target_os = "fuchsia",
528 solarish,
529 target_os = "redox"
530 ))]
531 fn len(&self) -> libc::socklen_t {
532 self.sun_len.into()
533 }
534
535 unsafe fn from_raw(
536 addr: *const libc::sockaddr,
537 len: Option<libc::socklen_t>,
538 ) -> Option<Self>
539 where
540 Self: Sized,
541 {
542 if let Some(l) = len {
543 if (l as usize) < offset_of!(libc::sockaddr_un, sun_path)
544 || l > u8::MAX as libc::socklen_t
545 {
546 return None;
547 }
548 }
549 if unsafe { (*addr).sa_family as i32 != libc::AF_UNIX } {
550 return None;
551 }
552 let mut su: libc::sockaddr_un = unsafe { mem::zeroed() };
553 let sup = &mut su as *mut libc::sockaddr_un as *mut u8;
554 cfg_if! {
555 if #[cfg(any(linux_android,
556 target_os = "fuchsia",
557 solarish,
558 target_os = "redox",
559 ))] {
560 let su_len = len.unwrap_or(
561 mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
562 );
563 } else {
564 let su_len = unsafe { len.unwrap_or((*addr).sa_len as libc::socklen_t) };
565 }
566 }
567 unsafe { ptr::copy(addr as *const u8, sup, su_len as usize) };
568 Some(unsafe { Self::from_raw_parts(su, su_len as u8) })
569 }
570
571 fn size() -> libc::socklen_t
572 where
573 Self: Sized,
574 {
575 mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
576 }
577
578 unsafe fn set_length(
579 &mut self,
580 new_length: usize,
581 ) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
582 #![allow(unused_variables)]
584 cfg_if! {
585 if #[cfg(any(linux_android,
586 target_os = "fuchsia",
587 solarish,
588 target_os = "redox",
589 ))] {
590 self.sun_len = new_length as u8;
591 }
592 };
593 Ok(())
594 }
595}
596
597impl AsRef<libc::sockaddr_un> for UnixAddr {
598 fn as_ref(&self) -> &libc::sockaddr_un {
599 &self.sun
600 }
601}
602
603#[cfg(linux_android)]
604fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
605 use fmt::Write;
606 f.write_str("@\"")?;
607 for &b in abs {
608 use fmt::Display;
609 char::from(b).escape_default().fmt(f)?;
610 }
611 f.write_char('"')?;
612 Ok(())
613}
614
615impl fmt::Display for UnixAddr {
616 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
617 match self.kind() {
618 UnixAddrKind::Pathname(path) => path.display().fmt(f),
619 UnixAddrKind::Unnamed => f.pad("<unbound UNIX socket>"),
620 #[cfg(linux_android)]
621 UnixAddrKind::Abstract(name) => fmt_abstract(name, f),
622 }
623 }
624}
625
626impl PartialEq for UnixAddr {
627 fn eq(&self, other: &UnixAddr) -> bool {
628 self.kind() == other.kind()
629 }
630}
631
632impl Eq for UnixAddr {}
633
634impl Hash for UnixAddr {
635 fn hash<H: Hasher>(&self, s: &mut H) {
636 self.kind().hash(s)
637 }
638}
639
640#[allow(clippy::len_without_is_empty)]
645pub trait SockaddrLike: private::SockaddrLikePriv {
646 fn as_ptr(&self) -> *const libc::sockaddr {
648 self as *const Self as *const libc::sockaddr
649 }
650
651 unsafe fn from_raw(
673 addr: *const libc::sockaddr,
674 len: Option<libc::socklen_t>,
675 ) -> Option<Self>
676 where
677 Self: Sized;
678
679 fn family(&self) -> Option<AddressFamily> {
696 AddressFamily::from_i32(unsafe {
699 (*(self as *const Self as *const libc::sockaddr)).sa_family as i32
700 })
701 }
702
703 cfg_if! {
704 if #[cfg(bsd)] {
705 fn len(&self) -> libc::socklen_t {
711 unsafe {
715 (*(self as *const Self as *const libc::sockaddr)).sa_len
716 }.into()
717 }
718 } else {
719 fn len(&self) -> libc::socklen_t {
725 mem::size_of_val(self) as libc::socklen_t
729 }
730 }
731 }
732
733 fn size() -> libc::socklen_t
735 where
736 Self: Sized,
737 {
738 mem::size_of::<Self>() as libc::socklen_t
739 }
740
741 #[doc(hidden)]
751 unsafe fn set_length(
752 &mut self,
753 _new_length: usize,
754 ) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
755 Err(SocketAddressLengthNotDynamic)
756 }
757}
758
759#[derive(Copy, Clone, Debug)]
762pub struct SocketAddressLengthNotDynamic;
763impl fmt::Display for SocketAddressLengthNotDynamic {
764 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
765 f.write_str("Attempted to set length on socket whose length is statically fixed")
766 }
767}
768impl std::error::Error for SocketAddressLengthNotDynamic {}
769
770impl private::SockaddrLikePriv for () {
771 fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
772 ptr::null_mut()
773 }
774}
775
776impl SockaddrLike for () {
781 fn as_ptr(&self) -> *const libc::sockaddr {
782 ptr::null()
783 }
784
785 unsafe fn from_raw(
786 _: *const libc::sockaddr,
787 _: Option<libc::socklen_t>,
788 ) -> Option<Self>
789 where
790 Self: Sized,
791 {
792 None
793 }
794
795 fn family(&self) -> Option<AddressFamily> {
796 None
797 }
798
799 fn len(&self) -> libc::socklen_t {
800 0
801 }
802}
803
804#[cfg(feature = "net")]
806#[repr(transparent)]
807#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
808pub struct SockaddrIn(libc::sockaddr_in);
809
810#[cfg(feature = "net")]
811impl SockaddrIn {
812 pub const fn ip(&self) -> net::Ipv4Addr {
815 let bytes = self.0.sin_addr.s_addr.to_ne_bytes();
816 let (a, b, c, d) = (bytes[0], bytes[1], bytes[2], bytes[3]);
817 Ipv4Addr::new(a, b, c, d)
818 }
819
820 pub fn new(a: u8, b: u8, c: u8, d: u8, port: u16) -> Self {
822 Self(libc::sockaddr_in {
823 #[cfg(any(
824 bsd,
825 target_os = "aix",
826 target_os = "haiku",
827 target_os = "hurd"
828 ))]
829 sin_len: Self::size() as u8,
830 sin_family: AddressFamily::Inet as sa_family_t,
831 sin_port: u16::to_be(port),
832 sin_addr: libc::in_addr {
833 s_addr: u32::from_ne_bytes([a, b, c, d]),
834 },
835 sin_zero: unsafe { mem::zeroed() },
836 })
837 }
838
839 pub const fn port(&self) -> u16 {
842 u16::from_be(self.0.sin_port)
843 }
844}
845
846#[cfg(feature = "net")]
847impl private::SockaddrLikePriv for SockaddrIn {}
848#[cfg(feature = "net")]
849impl SockaddrLike for SockaddrIn {
850 unsafe fn from_raw(
851 addr: *const libc::sockaddr,
852 len: Option<libc::socklen_t>,
853 ) -> Option<Self>
854 where
855 Self: Sized,
856 {
857 if let Some(l) = len {
858 if l != mem::size_of::<libc::sockaddr_in>() as libc::socklen_t {
859 return None;
860 }
861 }
862 if unsafe { (*addr).sa_family as i32 != libc::AF_INET } {
863 return None;
864 }
865 Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
866 }
867}
868
869#[cfg(feature = "net")]
870impl AsRef<libc::sockaddr_in> for SockaddrIn {
871 fn as_ref(&self) -> &libc::sockaddr_in {
872 &self.0
873 }
874}
875
876#[cfg(feature = "net")]
877impl fmt::Display for SockaddrIn {
878 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
879 let ne = u32::from_be(self.0.sin_addr.s_addr);
880 let port = u16::from_be(self.0.sin_port);
881 write!(
882 f,
883 "{}.{}.{}.{}:{}",
884 ne >> 24,
885 (ne >> 16) & 0xFF,
886 (ne >> 8) & 0xFF,
887 ne & 0xFF,
888 port
889 )
890 }
891}
892
893#[cfg(feature = "net")]
894impl From<net::SocketAddrV4> for SockaddrIn {
895 fn from(addr: net::SocketAddrV4) -> Self {
896 Self(libc::sockaddr_in {
897 #[cfg(any(
898 bsd,
899 target_os = "haiku",
900 target_os = "hermit",
901 target_os = "hurd"
902 ))]
903 sin_len: mem::size_of::<libc::sockaddr_in>() as u8,
904 sin_family: AddressFamily::Inet as sa_family_t,
905 sin_port: addr.port().to_be(), sin_addr: ipv4addr_to_libc(*addr.ip()),
907 ..unsafe { mem::zeroed() }
908 })
909 }
910}
911
912#[cfg(feature = "net")]
913impl From<SockaddrIn> for net::SocketAddrV4 {
914 fn from(addr: SockaddrIn) -> Self {
915 net::SocketAddrV4::new(
916 net::Ipv4Addr::from(addr.0.sin_addr.s_addr.to_ne_bytes()),
917 u16::from_be(addr.0.sin_port),
918 )
919 }
920}
921
922#[cfg(feature = "net")]
923impl From<SockaddrIn> for libc::sockaddr_in {
924 fn from(sin: SockaddrIn) -> libc::sockaddr_in {
925 sin.0
926 }
927}
928#[cfg(feature = "net")]
929impl From<libc::sockaddr_in> for SockaddrIn {
930 fn from(sin: libc::sockaddr_in) -> SockaddrIn {
931 SockaddrIn(sin)
932 }
933}
934
935#[cfg(feature = "net")]
936impl std::str::FromStr for SockaddrIn {
937 type Err = net::AddrParseError;
938
939 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
940 net::SocketAddrV4::from_str(s).map(SockaddrIn::from)
941 }
942}
943
944#[cfg(feature = "net")]
946#[repr(transparent)]
947#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
948pub struct SockaddrIn6(libc::sockaddr_in6);
949
950#[cfg(feature = "net")]
951impl SockaddrIn6 {
952 pub const fn flowinfo(&self) -> u32 {
954 self.0.sin6_flowinfo
955 }
956
957 pub const fn ip(&self) -> net::Ipv6Addr {
959 let bytes = self.0.sin6_addr.s6_addr;
960 let (a, b, c, d, e, f, g, h) = (
961 ((bytes[0] as u16) << 8) | bytes[1] as u16,
962 ((bytes[2] as u16) << 8) | bytes[3] as u16,
963 ((bytes[4] as u16) << 8) | bytes[5] as u16,
964 ((bytes[6] as u16) << 8) | bytes[7] as u16,
965 ((bytes[8] as u16) << 8) | bytes[9] as u16,
966 ((bytes[10] as u16) << 8) | bytes[11] as u16,
967 ((bytes[12] as u16) << 8) | bytes[13] as u16,
968 ((bytes[14] as u16) << 8) | bytes[15] as u16,
969 );
970 Ipv6Addr::new(a, b, c, d, e, f, g, h)
971 }
972
973 pub const fn port(&self) -> u16 {
976 u16::from_be(self.0.sin6_port)
977 }
978
979 pub const fn scope_id(&self) -> u32 {
981 self.0.sin6_scope_id
982 }
983}
984
985#[cfg(feature = "net")]
986impl From<SockaddrIn6> for libc::sockaddr_in6 {
987 fn from(sin6: SockaddrIn6) -> libc::sockaddr_in6 {
988 sin6.0
989 }
990}
991
992#[cfg(feature = "net")]
993impl From<libc::sockaddr_in6> for SockaddrIn6 {
994 fn from(sin6: libc::sockaddr_in6) -> SockaddrIn6 {
995 SockaddrIn6(sin6)
996 }
997}
998
999#[cfg(feature = "net")]
1000impl private::SockaddrLikePriv for SockaddrIn6 {}
1001#[cfg(feature = "net")]
1002impl SockaddrLike for SockaddrIn6 {
1003 unsafe fn from_raw(
1004 addr: *const libc::sockaddr,
1005 len: Option<libc::socklen_t>,
1006 ) -> Option<Self>
1007 where
1008 Self: Sized,
1009 {
1010 if let Some(l) = len {
1011 if l != mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t {
1012 return None;
1013 }
1014 }
1015 if unsafe { (*addr).sa_family as i32 != libc::AF_INET6 } {
1016 return None;
1017 }
1018 Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
1019 }
1020}
1021
1022#[cfg(feature = "net")]
1023impl AsRef<libc::sockaddr_in6> for SockaddrIn6 {
1024 fn as_ref(&self) -> &libc::sockaddr_in6 {
1025 &self.0
1026 }
1027}
1028
1029#[cfg(feature = "net")]
1030impl fmt::Display for SockaddrIn6 {
1031 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1032 let std = net::SocketAddrV6::new(
1035 self.ip(),
1036 self.port(),
1037 self.flowinfo(),
1038 self.scope_id(),
1039 );
1040 std.fmt(f)
1041 }
1042}
1043
1044#[cfg(feature = "net")]
1045impl From<net::SocketAddrV6> for SockaddrIn6 {
1046 fn from(addr: net::SocketAddrV6) -> Self {
1047 #[allow(clippy::needless_update)] Self(libc::sockaddr_in6 {
1049 #[cfg(any(
1050 bsd,
1051 target_os = "haiku",
1052 target_os = "hermit",
1053 target_os = "hurd"
1054 ))]
1055 sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8,
1056 sin6_family: AddressFamily::Inet6 as sa_family_t,
1057 sin6_port: addr.port().to_be(), sin6_addr: ipv6addr_to_libc(addr.ip()),
1059 sin6_flowinfo: addr.flowinfo(), sin6_scope_id: addr.scope_id(), ..unsafe { mem::zeroed() }
1062 })
1063 }
1064}
1065
1066#[cfg(feature = "net")]
1067impl From<SockaddrIn6> for net::SocketAddrV6 {
1068 fn from(addr: SockaddrIn6) -> Self {
1069 net::SocketAddrV6::new(
1070 net::Ipv6Addr::from(addr.0.sin6_addr.s6_addr),
1071 u16::from_be(addr.0.sin6_port),
1072 addr.0.sin6_flowinfo,
1073 addr.0.sin6_scope_id,
1074 )
1075 }
1076}
1077
1078#[cfg(feature = "net")]
1079impl std::str::FromStr for SockaddrIn6 {
1080 type Err = net::AddrParseError;
1081
1082 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
1083 net::SocketAddrV6::from_str(s).map(SockaddrIn6::from)
1084 }
1085}
1086
1087#[derive(Clone, Copy, Eq)]
1107#[repr(C)]
1108pub union SockaddrStorage {
1109 #[cfg(linux_android)]
1110 alg: AlgAddr,
1111 #[cfg(all(
1112 feature = "net",
1113 not(any(target_os = "hurd", target_os = "redox"))
1114 ))]
1115 #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
1116 dl: LinkAddr,
1117 #[cfg(linux_android)]
1118 nl: NetlinkAddr,
1119 #[cfg(all(feature = "ioctl", apple_targets))]
1120 #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
1121 sctl: SysControlAddr,
1122 #[cfg(feature = "net")]
1123 sin: SockaddrIn,
1124 #[cfg(feature = "net")]
1125 sin6: SockaddrIn6,
1126 ss: libc::sockaddr_storage,
1127 su: UnixAddr,
1128 #[cfg(any(linux_android, apple_targets))]
1129 vsock: VsockAddr,
1130}
1131impl private::SockaddrLikePriv for SockaddrStorage {}
1132impl SockaddrLike for SockaddrStorage {
1133 unsafe fn from_raw(
1134 addr: *const libc::sockaddr,
1135 l: Option<libc::socklen_t>,
1136 ) -> Option<Self>
1137 where
1138 Self: Sized,
1139 {
1140 if addr.is_null() {
1141 return None;
1142 }
1143 if let Some(len) = l {
1144 let ulen = len as usize;
1145 if ulen < offset_of!(libc::sockaddr, sa_data)
1146 || ulen > mem::size_of::<libc::sockaddr_storage>()
1147 {
1148 None
1149 } else {
1150 let mut ss: libc::sockaddr_storage = unsafe { mem::zeroed() };
1151 let ssp = &mut ss as *mut libc::sockaddr_storage as *mut u8;
1152 unsafe { ptr::copy(addr as *const u8, ssp, len as usize) };
1153 #[cfg(any(
1154 linux_android,
1155 target_os = "fuchsia",
1156 solarish,
1157 ))]
1158 if i32::from(ss.ss_family) == libc::AF_UNIX {
1159 unsafe {
1162 (*(&mut ss as *mut libc::sockaddr_storage
1163 as *mut UnixAddr))
1164 .sun_len = len as u8;
1165 }
1166 }
1167 Some(Self { ss })
1168 }
1169 } else {
1170 match unsafe { (*addr).sa_family as i32 } {
1174 #[cfg(linux_android)]
1175 libc::AF_ALG => unsafe {
1176 AlgAddr::from_raw(addr, l).map(|alg| Self { alg })
1177 },
1178 #[cfg(feature = "net")]
1179 libc::AF_INET => unsafe {
1180 SockaddrIn::from_raw(addr, l).map(|sin| Self { sin })
1181 },
1182 #[cfg(feature = "net")]
1183 libc::AF_INET6 => unsafe {
1184 SockaddrIn6::from_raw(addr, l).map(|sin6| Self { sin6 })
1185 },
1186 #[cfg(any(bsd, solarish, target_os = "haiku"))]
1187 #[cfg(feature = "net")]
1188 libc::AF_LINK => unsafe {
1189 LinkAddr::from_raw(addr, l).map(|dl| Self { dl })
1190 },
1191 #[cfg(linux_android)]
1192 libc::AF_NETLINK => unsafe {
1193 NetlinkAddr::from_raw(addr, l).map(|nl| Self { nl })
1194 },
1195 #[cfg(any(linux_android, target_os = "fuchsia"))]
1196 #[cfg(feature = "net")]
1197 libc::AF_PACKET => unsafe {
1198 LinkAddr::from_raw(addr, l).map(|dl| Self { dl })
1199 },
1200 #[cfg(all(feature = "ioctl", apple_targets))]
1201 libc::AF_SYSTEM => unsafe {
1202 SysControlAddr::from_raw(addr, l).map(|sctl| Self { sctl })
1203 },
1204 #[cfg(any(linux_android, apple_targets))]
1205 libc::AF_VSOCK => unsafe {
1206 VsockAddr::from_raw(addr, l).map(|vsock| Self { vsock })
1207 },
1208 _ => None,
1209 }
1210 }
1211 }
1212
1213 #[cfg(any(linux_android, target_os = "fuchsia", solarish))]
1214 fn len(&self) -> libc::socklen_t {
1215 match self.as_unix_addr() {
1216 Some(ua) => ua.len(),
1218 None => mem::size_of_val(self) as libc::socklen_t,
1220 }
1221 }
1222
1223 unsafe fn set_length(
1224 &mut self,
1225 new_length: usize,
1226 ) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
1227 match self.as_unix_addr_mut() {
1228 Some(addr) => unsafe { addr.set_length(new_length) },
1229 None => Err(SocketAddressLengthNotDynamic),
1230 }
1231 }
1232}
1233
1234macro_rules! accessors {
1235 (
1236 $fname:ident,
1237 $fname_mut:ident,
1238 $sockty:ty,
1239 $family:expr,
1240 $libc_ty:ty,
1241 $field:ident) => {
1242 pub fn $fname(&self) -> Option<&$sockty> {
1244 if self.family() == Some($family)
1245 && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
1246 {
1247 Some(unsafe { &self.$field })
1249 } else {
1250 None
1251 }
1252 }
1253
1254 pub fn $fname_mut(&mut self) -> Option<&mut $sockty> {
1256 if self.family() == Some($family)
1257 && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
1258 {
1259 Some(unsafe { &mut self.$field })
1261 } else {
1262 None
1263 }
1264 }
1265 };
1266}
1267
1268impl SockaddrStorage {
1269 pub fn as_unix_addr(&self) -> Option<&UnixAddr> {
1271 cfg_if! {
1272 if #[cfg(any(linux_android,
1273 target_os = "fuchsia",
1274 solarish,
1275 ))]
1276 {
1277 let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
1278 let len = unsafe {
1281 (*(p as *const UnixAddr )).sun_len as usize
1282 };
1283 } else {
1284 let len = self.len() as usize;
1285 }
1286 }
1287 if self.family() != Some(AddressFamily::Unix)
1289 || len < offset_of!(libc::sockaddr_un, sun_path)
1290 || len > mem::size_of::<libc::sockaddr_un>()
1291 {
1292 None
1293 } else {
1294 Some(unsafe { &self.su })
1295 }
1296 }
1297
1298 pub fn as_unix_addr_mut(&mut self) -> Option<&mut UnixAddr> {
1300 cfg_if! {
1301 if #[cfg(any(linux_android,
1302 target_os = "fuchsia",
1303 solarish,
1304 ))]
1305 {
1306 let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
1307 let len = unsafe {
1310 (*(p as *const UnixAddr )).sun_len as usize
1311 };
1312 } else {
1313 let len = self.len() as usize;
1314 }
1315 }
1316 if self.family() != Some(AddressFamily::Unix)
1318 || len < offset_of!(libc::sockaddr_un, sun_path)
1319 || len > mem::size_of::<libc::sockaddr_un>()
1320 {
1321 None
1322 } else {
1323 Some(unsafe { &mut self.su })
1324 }
1325 }
1326
1327 #[cfg(linux_android)]
1328 accessors! {as_alg_addr, as_alg_addr_mut, AlgAddr,
1329 AddressFamily::Alg, libc::sockaddr_alg, alg}
1330
1331 #[cfg(any(linux_android, target_os = "fuchsia"))]
1332 #[cfg(feature = "net")]
1333 accessors! {
1334 as_link_addr, as_link_addr_mut, LinkAddr,
1335 AddressFamily::Packet, libc::sockaddr_ll, dl}
1336
1337 #[cfg(any(bsd, solarish))]
1338 #[cfg(feature = "net")]
1339 accessors! {
1340 as_link_addr, as_link_addr_mut, LinkAddr,
1341 AddressFamily::Link, libc::sockaddr_dl, dl}
1342
1343 #[cfg(feature = "net")]
1344 accessors! {
1345 as_sockaddr_in, as_sockaddr_in_mut, SockaddrIn,
1346 AddressFamily::Inet, libc::sockaddr_in, sin}
1347
1348 #[cfg(feature = "net")]
1349 accessors! {
1350 as_sockaddr_in6, as_sockaddr_in6_mut, SockaddrIn6,
1351 AddressFamily::Inet6, libc::sockaddr_in6, sin6}
1352
1353 #[cfg(linux_android)]
1354 accessors! {as_netlink_addr, as_netlink_addr_mut, NetlinkAddr,
1355 AddressFamily::Netlink, libc::sockaddr_nl, nl}
1356
1357 #[cfg(all(feature = "ioctl", apple_targets))]
1358 #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
1359 accessors! {as_sys_control_addr, as_sys_control_addr_mut, SysControlAddr,
1360 AddressFamily::System, libc::sockaddr_ctl, sctl}
1361
1362 #[cfg(any(linux_android, apple_targets))]
1363 accessors! {as_vsock_addr, as_vsock_addr_mut, VsockAddr,
1364 AddressFamily::Vsock, libc::sockaddr_vm, vsock}
1365}
1366
1367impl fmt::Debug for SockaddrStorage {
1368 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1369 f.debug_struct("SockaddrStorage")
1370 .field("ss", unsafe { &self.ss })
1373 .finish()
1374 }
1375}
1376
1377impl fmt::Display for SockaddrStorage {
1378 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1379 unsafe {
1380 match self.ss.ss_family as i32 {
1381 #[cfg(linux_android)]
1382 libc::AF_ALG => self.alg.fmt(f),
1383 #[cfg(feature = "net")]
1384 libc::AF_INET => self.sin.fmt(f),
1385 #[cfg(feature = "net")]
1386 libc::AF_INET6 => self.sin6.fmt(f),
1387 #[cfg(any(bsd, solarish))]
1388 #[cfg(feature = "net")]
1389 libc::AF_LINK => self.dl.fmt(f),
1390 #[cfg(linux_android)]
1391 libc::AF_NETLINK => self.nl.fmt(f),
1392 #[cfg(any(linux_android, target_os = "fuchsia"))]
1393 #[cfg(feature = "net")]
1394 libc::AF_PACKET => self.dl.fmt(f),
1395 #[cfg(apple_targets)]
1396 #[cfg(feature = "ioctl")]
1397 libc::AF_SYSTEM => self.sctl.fmt(f),
1398 libc::AF_UNIX => self.su.fmt(f),
1399 #[cfg(any(linux_android, apple_targets))]
1400 libc::AF_VSOCK => self.vsock.fmt(f),
1401 _ => "<Address family unspecified>".fmt(f),
1402 }
1403 }
1404 }
1405}
1406
1407#[cfg(feature = "net")]
1408impl From<net::SocketAddrV4> for SockaddrStorage {
1409 fn from(s: net::SocketAddrV4) -> Self {
1410 unsafe {
1411 let mut ss: Self = mem::zeroed();
1412 ss.sin = SockaddrIn::from(s);
1413 ss
1414 }
1415 }
1416}
1417
1418#[cfg(feature = "net")]
1419impl From<net::SocketAddrV6> for SockaddrStorage {
1420 fn from(s: net::SocketAddrV6) -> Self {
1421 unsafe {
1422 let mut ss: Self = mem::zeroed();
1423 ss.sin6 = SockaddrIn6::from(s);
1424 ss
1425 }
1426 }
1427}
1428
1429#[cfg(feature = "net")]
1430impl From<net::SocketAddr> for SockaddrStorage {
1431 fn from(s: net::SocketAddr) -> Self {
1432 match s {
1433 net::SocketAddr::V4(sa4) => Self::from(sa4),
1434 net::SocketAddr::V6(sa6) => Self::from(sa6),
1435 }
1436 }
1437}
1438
1439impl Hash for SockaddrStorage {
1440 fn hash<H: Hasher>(&self, s: &mut H) {
1441 unsafe {
1442 match self.ss.ss_family as i32 {
1443 #[cfg(linux_android)]
1444 libc::AF_ALG => self.alg.hash(s),
1445 #[cfg(feature = "net")]
1446 libc::AF_INET => self.sin.hash(s),
1447 #[cfg(feature = "net")]
1448 libc::AF_INET6 => self.sin6.hash(s),
1449 #[cfg(any(bsd, solarish))]
1450 #[cfg(feature = "net")]
1451 libc::AF_LINK => self.dl.hash(s),
1452 #[cfg(linux_android)]
1453 libc::AF_NETLINK => self.nl.hash(s),
1454 #[cfg(any(linux_android, target_os = "fuchsia"))]
1455 #[cfg(feature = "net")]
1456 libc::AF_PACKET => self.dl.hash(s),
1457 #[cfg(apple_targets)]
1458 #[cfg(feature = "ioctl")]
1459 libc::AF_SYSTEM => self.sctl.hash(s),
1460 libc::AF_UNIX => self.su.hash(s),
1461 #[cfg(any(linux_android, apple_targets))]
1462 libc::AF_VSOCK => self.vsock.hash(s),
1463 _ => self.ss.hash(s),
1464 }
1465 }
1466 }
1467}
1468
1469impl PartialEq for SockaddrStorage {
1470 fn eq(&self, other: &Self) -> bool {
1471 unsafe {
1472 match (self.ss.ss_family as i32, other.ss.ss_family as i32) {
1473 #[cfg(linux_android)]
1474 (libc::AF_ALG, libc::AF_ALG) => self.alg == other.alg,
1475 #[cfg(feature = "net")]
1476 (libc::AF_INET, libc::AF_INET) => self.sin == other.sin,
1477 #[cfg(feature = "net")]
1478 (libc::AF_INET6, libc::AF_INET6) => self.sin6 == other.sin6,
1479 #[cfg(any(bsd, solarish))]
1480 #[cfg(feature = "net")]
1481 (libc::AF_LINK, libc::AF_LINK) => self.dl == other.dl,
1482 #[cfg(linux_android)]
1483 (libc::AF_NETLINK, libc::AF_NETLINK) => self.nl == other.nl,
1484 #[cfg(any(linux_android, target_os = "fuchsia"))]
1485 #[cfg(feature = "net")]
1486 (libc::AF_PACKET, libc::AF_PACKET) => self.dl == other.dl,
1487 #[cfg(apple_targets)]
1488 #[cfg(feature = "ioctl")]
1489 (libc::AF_SYSTEM, libc::AF_SYSTEM) => self.sctl == other.sctl,
1490 (libc::AF_UNIX, libc::AF_UNIX) => self.su == other.su,
1491 #[cfg(any(linux_android, apple_targets))]
1492 (libc::AF_VSOCK, libc::AF_VSOCK) => self.vsock == other.vsock,
1493 _ => false,
1494 }
1495 }
1496 }
1497}
1498
1499pub(super) mod private {
1500 pub trait SockaddrLikePriv {
1501 fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
1510 self as *mut Self as *mut libc::sockaddr
1511 }
1512 }
1513}
1514
1515#[cfg(linux_android)]
1516pub mod netlink {
1517 use super::*;
1518 use crate::sys::socket::addr::AddressFamily;
1519 use libc::{sa_family_t, sockaddr_nl};
1520 use std::{fmt, mem};
1521
1522 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
1528 #[repr(transparent)]
1529 pub struct NetlinkAddr(pub(in super::super) sockaddr_nl);
1530
1531 impl NetlinkAddr {
1532 pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
1535 let mut addr: sockaddr_nl = unsafe { mem::zeroed() };
1536 addr.nl_family = AddressFamily::Netlink as sa_family_t;
1537 addr.nl_pid = pid;
1538 addr.nl_groups = groups;
1539
1540 NetlinkAddr(addr)
1541 }
1542
1543 pub const fn pid(&self) -> u32 {
1545 self.0.nl_pid
1546 }
1547
1548 pub const fn groups(&self) -> u32 {
1550 self.0.nl_groups
1551 }
1552 }
1553
1554 impl private::SockaddrLikePriv for NetlinkAddr {}
1555 impl SockaddrLike for NetlinkAddr {
1556 unsafe fn from_raw(
1557 addr: *const libc::sockaddr,
1558 len: Option<libc::socklen_t>,
1559 ) -> Option<Self>
1560 where
1561 Self: Sized,
1562 {
1563 if let Some(l) = len {
1564 if l != mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t {
1565 return None;
1566 }
1567 }
1568 if unsafe { (*addr).sa_family as i32 != libc::AF_NETLINK } {
1569 return None;
1570 }
1571 Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
1572 }
1573 }
1574
1575 impl AsRef<libc::sockaddr_nl> for NetlinkAddr {
1576 fn as_ref(&self) -> &libc::sockaddr_nl {
1577 &self.0
1578 }
1579 }
1580
1581 impl fmt::Display for NetlinkAddr {
1582 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1583 write!(f, "pid: {} groups: {}", self.pid(), self.groups())
1584 }
1585 }
1586}
1587
1588#[cfg(linux_android)]
1589pub mod alg {
1590 use super::*;
1591 use libc::{sockaddr_alg, AF_ALG};
1592 use std::ffi::CStr;
1593 use std::hash::{Hash, Hasher};
1594 use std::{fmt, mem, str};
1595
1596 #[derive(Copy, Clone)]
1598 #[repr(transparent)]
1599 pub struct AlgAddr(pub(in super::super) sockaddr_alg);
1600
1601 impl private::SockaddrLikePriv for AlgAddr {}
1602 impl SockaddrLike for AlgAddr {
1603 unsafe fn from_raw(
1604 addr: *const libc::sockaddr,
1605 l: Option<libc::socklen_t>,
1606 ) -> Option<Self>
1607 where
1608 Self: Sized,
1609 {
1610 if let Some(l) = l {
1611 if l != mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t
1612 {
1613 return None;
1614 }
1615 }
1616 if unsafe { (*addr).sa_family as i32 != libc::AF_ALG } {
1617 return None;
1618 }
1619 Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
1620 }
1621 }
1622
1623 impl AsRef<libc::sockaddr_alg> for AlgAddr {
1624 fn as_ref(&self) -> &libc::sockaddr_alg {
1625 &self.0
1626 }
1627 }
1628
1629 impl PartialEq for AlgAddr {
1631 fn eq(&self, other: &Self) -> bool {
1632 let (inner, other) = (self.0, other.0);
1633 (
1634 inner.salg_family,
1635 &inner.salg_type[..],
1636 inner.salg_feat,
1637 inner.salg_mask,
1638 &inner.salg_name[..],
1639 ) == (
1640 other.salg_family,
1641 &other.salg_type[..],
1642 other.salg_feat,
1643 other.salg_mask,
1644 &other.salg_name[..],
1645 )
1646 }
1647 }
1648
1649 impl Eq for AlgAddr {}
1650
1651 impl Hash for AlgAddr {
1652 fn hash<H: Hasher>(&self, s: &mut H) {
1653 let inner = self.0;
1654 (
1655 inner.salg_family,
1656 &inner.salg_type[..],
1657 inner.salg_feat,
1658 inner.salg_mask,
1659 &inner.salg_name[..],
1660 )
1661 .hash(s);
1662 }
1663 }
1664
1665 impl AlgAddr {
1666 pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
1668 let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
1669 addr.salg_family = AF_ALG as u16;
1670 addr.salg_type[..alg_type.len()]
1671 .copy_from_slice(alg_type.to_string().as_bytes());
1672 addr.salg_name[..alg_name.len()]
1673 .copy_from_slice(alg_name.to_string().as_bytes());
1674
1675 AlgAddr(addr)
1676 }
1677
1678 pub fn alg_type(&self) -> &CStr {
1680 unsafe { CStr::from_ptr(self.0.salg_type.as_ptr().cast()) }
1681 }
1682
1683 pub fn alg_name(&self) -> &CStr {
1685 unsafe { CStr::from_ptr(self.0.salg_name.as_ptr().cast()) }
1686 }
1687 }
1688
1689 impl fmt::Display for AlgAddr {
1690 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1691 write!(
1692 f,
1693 "type: {} alg: {}",
1694 self.alg_name().to_string_lossy(),
1695 self.alg_type().to_string_lossy()
1696 )
1697 }
1698 }
1699
1700 impl fmt::Debug for AlgAddr {
1701 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1702 fmt::Display::fmt(self, f)
1703 }
1704 }
1705}
1706
1707feature! {
1708#![feature = "ioctl"]
1709#[cfg(apple_targets)]
1710pub mod sys_control {
1711 use crate::sys::socket::addr::AddressFamily;
1712 use libc::{self, c_uchar};
1713 use std::{fmt, mem, ptr};
1714 use std::os::unix::io::RawFd;
1715 use crate::{Errno, Result};
1716 use super::{private, SockaddrLike};
1717
1718 #[repr(C)]
1720 #[derive(Clone, Copy)]
1721 #[allow(missing_debug_implementations)]
1722 pub struct ctl_ioc_info {
1723 pub ctl_id: u32,
1724 pub ctl_name: [c_uchar; MAX_KCTL_NAME],
1725 }
1726
1727 const CTL_IOC_MAGIC: u8 = b'N';
1728 const CTL_IOC_INFO: u8 = 3;
1729 const MAX_KCTL_NAME: usize = 96;
1730
1731 ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info);
1732
1733 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1739 #[repr(transparent)]
1740 pub struct SysControlAddr(pub(in super::super) libc::sockaddr_ctl);
1741
1742 impl private::SockaddrLikePriv for SysControlAddr {}
1743 impl SockaddrLike for SysControlAddr {
1744 unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
1745 -> Option<Self> where Self: Sized
1746 {
1747 if let Some(l) = len {
1748 if l != mem::size_of::<libc::sockaddr_ctl>() as libc::socklen_t {
1749 return None;
1750 }
1751 }
1752 if unsafe { (*addr).sa_family as i32 != libc::AF_SYSTEM } {
1753 return None;
1754 }
1755 Some(Self(unsafe { ptr::read_unaligned(addr as *const _) } ))
1756 }
1757 }
1758
1759 impl AsRef<libc::sockaddr_ctl> for SysControlAddr {
1760 fn as_ref(&self) -> &libc::sockaddr_ctl {
1761 &self.0
1762 }
1763 }
1764
1765 impl SysControlAddr {
1766 pub const fn new(id: u32, unit: u32) -> SysControlAddr {
1769 let addr = libc::sockaddr_ctl {
1770 sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
1771 sc_family: AddressFamily::System as c_uchar,
1772 ss_sysaddr: libc::AF_SYS_CONTROL as u16,
1773 sc_id: id,
1774 sc_unit: unit,
1775 sc_reserved: [0; 5]
1776 };
1777
1778 SysControlAddr(addr)
1779 }
1780
1781 pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
1784 if name.len() > MAX_KCTL_NAME {
1785 return Err(Errno::ENAMETOOLONG);
1786 }
1787
1788 let mut ctl_name = [0; MAX_KCTL_NAME];
1789 ctl_name[..name.len()].clone_from_slice(name.as_bytes());
1790 let mut info = ctl_ioc_info { ctl_id: 0, ctl_name };
1791
1792 unsafe { ctl_info(sockfd, &mut info)?; }
1793
1794 Ok(SysControlAddr::new(info.ctl_id, unit))
1795 }
1796
1797 pub const fn id(&self) -> u32 {
1799 self.0.sc_id
1800 }
1801
1802 pub const fn unit(&self) -> u32 {
1804 self.0.sc_unit
1805 }
1806 }
1807
1808 impl fmt::Display for SysControlAddr {
1809 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1810 fmt::Debug::fmt(self, f)
1811 }
1812 }
1813}
1814}
1815
1816#[cfg(any(linux_android, target_os = "fuchsia"))]
1817mod datalink {
1818 feature! {
1819 #![feature = "net"]
1820 use super::{fmt, mem, private, ptr, SockaddrLike};
1821
1822 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1824 #[repr(transparent)]
1825 pub struct LinkAddr(pub(in super::super) libc::sockaddr_ll);
1826
1827 impl LinkAddr {
1828 pub fn protocol(&self) -> u16 {
1830 self.0.sll_protocol
1831 }
1832
1833 pub fn ifindex(&self) -> usize {
1835 self.0.sll_ifindex as usize
1836 }
1837
1838 pub fn hatype(&self) -> u16 {
1840 self.0.sll_hatype
1841 }
1842
1843 pub fn pkttype(&self) -> u8 {
1845 self.0.sll_pkttype
1846 }
1847
1848 pub fn halen(&self) -> usize {
1850 self.0.sll_halen as usize
1851 }
1852
1853 pub fn addr(&self) -> Option<[u8; 6]> {
1856 Some([
1857 self.0.sll_addr[0],
1858 self.0.sll_addr[1],
1859 self.0.sll_addr[2],
1860 self.0.sll_addr[3],
1861 self.0.sll_addr[4],
1862 self.0.sll_addr[5],
1863 ])
1864 }
1865 }
1866
1867 impl fmt::Display for LinkAddr {
1868 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1869 if let Some(addr) = self.addr() {
1870 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1871 addr[0],
1872 addr[1],
1873 addr[2],
1874 addr[3],
1875 addr[4],
1876 addr[5])
1877 } else {
1878 Ok(())
1879 }
1880 }
1881 }
1882 impl private::SockaddrLikePriv for LinkAddr {}
1883 impl SockaddrLike for LinkAddr {
1884 unsafe fn from_raw(addr: *const libc::sockaddr,
1885 len: Option<libc::socklen_t>)
1886 -> Option<Self> where Self: Sized
1887 {
1888 if let Some(l) = len {
1889 if l != mem::size_of::<libc::sockaddr_ll>() as libc::socklen_t {
1890 return None;
1891 }
1892 }
1893 if unsafe { (*addr).sa_family as i32 != libc::AF_PACKET } {
1894 return None;
1895 }
1896 Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
1897 }
1898 }
1899
1900 impl AsRef<libc::sockaddr_ll> for LinkAddr {
1901 fn as_ref(&self) -> &libc::sockaddr_ll {
1902 &self.0
1903 }
1904 }
1905
1906 }
1907}
1908
1909#[cfg(any(bsd, solarish, target_os = "haiku", target_os = "aix"))]
1910mod datalink {
1911 feature! {
1912 #![feature = "net"]
1913 use super::{fmt, mem, private, ptr, SockaddrLike};
1914
1915 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1917 #[repr(transparent)]
1918 pub struct LinkAddr(pub(in super::super) libc::sockaddr_dl);
1919
1920 impl LinkAddr {
1921 #[cfg(not(target_os = "haiku"))]
1923 pub fn ifindex(&self) -> usize {
1924 self.0.sdl_index as usize
1925 }
1926
1927 #[cfg(not(target_os = "haiku"))]
1929 pub fn datalink_type(&self) -> u8 {
1930 self.0.sdl_type
1931 }
1932
1933 pub fn nlen(&self) -> usize {
1935 self.0.sdl_nlen as usize
1936 }
1937
1938 pub fn alen(&self) -> usize {
1940 self.0.sdl_alen as usize
1941 }
1942
1943 #[cfg(not(target_os = "haiku"))]
1945 pub fn slen(&self) -> usize {
1946 self.0.sdl_slen as usize
1947 }
1948
1949 pub fn is_empty(&self) -> bool {
1952 let nlen = self.nlen();
1953 let alen = self.alen();
1954 let data_len = self.0.sdl_data.len();
1955
1956 alen == 0 || nlen + alen >= data_len
1957 }
1958
1959 #[allow(clippy::unnecessary_cast)]
1962 pub fn addr(&self) -> Option<[u8; 6]> {
1963 let nlen = self.nlen();
1964 let data = self.0.sdl_data;
1965
1966 if self.is_empty() {
1967 None
1968 } else {
1969 Some([
1970 data[nlen] as u8,
1971 data[nlen + 1] as u8,
1972 data[nlen + 2] as u8,
1973 data[nlen + 3] as u8,
1974 data[nlen + 4] as u8,
1975 data[nlen + 5] as u8,
1976 ])
1977 }
1978 }
1979 }
1980
1981 impl fmt::Display for LinkAddr {
1982 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1983 if let Some(addr) = self.addr() {
1984 write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
1985 addr[0],
1986 addr[1],
1987 addr[2],
1988 addr[3],
1989 addr[4],
1990 addr[5])
1991 } else {
1992 Ok(())
1993 }
1994 }
1995 }
1996 impl private::SockaddrLikePriv for LinkAddr {}
1997 impl SockaddrLike for LinkAddr {
1998 unsafe fn from_raw(addr: *const libc::sockaddr,
1999 len: Option<libc::socklen_t>)
2000 -> Option<Self> where Self: Sized
2001 {
2002 if let Some(l) = len {
2003 if l != mem::size_of::<libc::sockaddr_dl>() as libc::socklen_t {
2004 return None;
2005 }
2006 }
2007 if unsafe { (*addr).sa_family as i32 != libc::AF_LINK } {
2008 return None;
2009 }
2010 Some(Self(unsafe { ptr::read_unaligned(addr as *const _) }))
2011 }
2012 }
2013
2014 impl AsRef<libc::sockaddr_dl> for LinkAddr {
2015 fn as_ref(&self) -> &libc::sockaddr_dl {
2016 &self.0
2017 }
2018 }
2019 }
2020}
2021
2022#[cfg(any(linux_android, apple_targets))]
2023pub mod vsock {
2024 use super::*;
2025 use crate::sys::socket::addr::AddressFamily;
2026 use libc::{sa_family_t, sockaddr_vm};
2027 use std::hash::{Hash, Hasher};
2028 use std::{fmt, mem};
2029
2030 #[derive(Copy, Clone)]
2036 #[repr(transparent)]
2037 pub struct VsockAddr(pub(in super::super) sockaddr_vm);
2038
2039 impl private::SockaddrLikePriv for VsockAddr {}
2040 impl SockaddrLike for VsockAddr {
2041 unsafe fn from_raw(
2042 addr: *const libc::sockaddr,
2043 len: Option<libc::socklen_t>,
2044 ) -> Option<Self>
2045 where
2046 Self: Sized,
2047 {
2048 if let Some(l) = len {
2049 if l != mem::size_of::<libc::sockaddr_vm>() as libc::socklen_t {
2050 return None;
2051 }
2052 }
2053 if unsafe { (*addr).sa_family as i32 != libc::AF_VSOCK } {
2054 return None;
2055 }
2056 unsafe { Some(Self(ptr::read_unaligned(addr as *const _))) }
2057 }
2058 }
2059
2060 impl AsRef<libc::sockaddr_vm> for VsockAddr {
2061 fn as_ref(&self) -> &libc::sockaddr_vm {
2062 &self.0
2063 }
2064 }
2065
2066 impl PartialEq for VsockAddr {
2067 #[cfg(linux_android)]
2068 fn eq(&self, other: &Self) -> bool {
2069 let (inner, other) = (self.0, other.0);
2070 (inner.svm_family, inner.svm_cid, inner.svm_port)
2071 == (other.svm_family, other.svm_cid, other.svm_port)
2072 }
2073 #[cfg(apple_targets)]
2074 fn eq(&self, other: &Self) -> bool {
2075 let (inner, other) = (self.0, other.0);
2076 (
2077 inner.svm_family,
2078 inner.svm_cid,
2079 inner.svm_port,
2080 inner.svm_len,
2081 ) == (
2082 other.svm_family,
2083 other.svm_cid,
2084 other.svm_port,
2085 inner.svm_len,
2086 )
2087 }
2088 }
2089
2090 impl Eq for VsockAddr {}
2091
2092 impl Hash for VsockAddr {
2093 #[cfg(linux_android)]
2094 fn hash<H: Hasher>(&self, s: &mut H) {
2095 let inner = self.0;
2096 (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
2097 }
2098 #[cfg(apple_targets)]
2099 fn hash<H: Hasher>(&self, s: &mut H) {
2100 let inner = self.0;
2101 (
2102 inner.svm_family,
2103 inner.svm_cid,
2104 inner.svm_port,
2105 inner.svm_len,
2106 )
2107 .hash(s);
2108 }
2109 }
2110
2111 impl VsockAddr {
2116 pub fn new(cid: u32, port: u32) -> VsockAddr {
2118 let mut addr: sockaddr_vm = unsafe { mem::zeroed() };
2119 addr.svm_family = AddressFamily::Vsock as sa_family_t;
2120 addr.svm_cid = cid;
2121 addr.svm_port = port;
2122
2123 #[cfg(apple_targets)]
2124 {
2125 addr.svm_len = std::mem::size_of::<sockaddr_vm>() as u8;
2126 }
2127 VsockAddr(addr)
2128 }
2129
2130 pub fn cid(&self) -> u32 {
2132 self.0.svm_cid
2133 }
2134
2135 pub fn port(&self) -> u32 {
2137 self.0.svm_port
2138 }
2139 }
2140
2141 impl fmt::Display for VsockAddr {
2142 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2143 write!(f, "cid: {} port: {}", self.cid(), self.port())
2144 }
2145 }
2146
2147 impl fmt::Debug for VsockAddr {
2148 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2149 fmt::Display::fmt(self, f)
2150 }
2151 }
2152}
2153
2154#[cfg(test)]
2155mod tests {
2156 use super::*;
2157
2158 mod types {
2159 use super::*;
2160
2161 #[test]
2162 fn test_ipv4addr_to_libc() {
2163 let s = std::net::Ipv4Addr::new(1, 2, 3, 4);
2164 let l = ipv4addr_to_libc(s);
2165 assert_eq!(l.s_addr, u32::to_be(0x01020304));
2166 }
2167
2168 #[test]
2169 fn test_ipv6addr_to_libc() {
2170 let s = std::net::Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8);
2171 let l = ipv6addr_to_libc(&s);
2172 assert_eq!(
2173 l.s6_addr,
2174 [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8]
2175 );
2176 }
2177 }
2178
2179 #[cfg(not(any(target_os = "hurd", target_os = "redox")))]
2180 #[allow(clippy::cast_ptr_alignment)]
2181 mod link {
2182 #[cfg(any(apple_targets, solarish))]
2183 use super::super::super::socklen_t;
2184 use super::*;
2185
2186 #[cfg(bsd)]
2188 #[test]
2189 fn test_datalink_display() {
2190 use super::super::LinkAddr;
2191 use std::mem;
2192
2193 let la = LinkAddr(libc::sockaddr_dl {
2194 sdl_len: 56,
2195 sdl_family: 18,
2196 sdl_index: 5,
2197 sdl_type: 24,
2198 sdl_nlen: 3,
2199 sdl_alen: 0,
2200 sdl_slen: 0,
2201 ..unsafe { mem::zeroed() }
2202 });
2203 format!("{la}");
2204 }
2205
2206 #[cfg(all(
2207 any(linux_android, target_os = "fuchsia"),
2208 target_endian = "little"
2209 ))]
2210 #[test]
2211 fn linux_loopback() {
2212 #[repr(align(2))]
2213 struct Raw([u8; 20]);
2214
2215 let bytes = Raw([
2216 17u8, 0, 0, 0, 1, 0, 0, 0, 4, 3, 0, 6, 1, 2, 3, 4, 5, 6, 0, 0,
2217 ]);
2218 let sa = bytes.0.as_ptr().cast();
2219 let len = None;
2220 let sock_addr =
2221 unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
2222 assert_eq!(sock_addr.family(), Some(AddressFamily::Packet));
2223 match sock_addr.as_link_addr() {
2224 Some(dl) => assert_eq!(dl.addr(), Some([1, 2, 3, 4, 5, 6])),
2225 None => panic!("Can't unwrap sockaddr storage"),
2226 }
2227 }
2228
2229 #[cfg(apple_targets)]
2230 #[test]
2231 fn macos_loopback() {
2232 let bytes =
2233 [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
2234 let sa = bytes.as_ptr().cast();
2235 let len = Some(bytes.len() as socklen_t);
2236 let sock_addr =
2237 unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
2238 assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
2239 match sock_addr.as_link_addr() {
2240 Some(dl) => {
2241 assert!(dl.addr().is_none());
2242 }
2243 None => panic!("Can't unwrap sockaddr storage"),
2244 }
2245 }
2246
2247 #[cfg(apple_targets)]
2248 #[test]
2249 fn macos_tap() {
2250 let bytes = [
2251 20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35,
2252 76, -80,
2253 ];
2254 let ptr = bytes.as_ptr();
2255 let sa = ptr as *const libc::sockaddr;
2256 let len = Some(bytes.len() as socklen_t);
2257
2258 let sock_addr =
2259 unsafe { SockaddrStorage::from_raw(sa, len).unwrap() };
2260 assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
2261 match sock_addr.as_link_addr() {
2262 Some(dl) => {
2263 assert_eq!(dl.addr(), Some([24u8, 101, 144, 221, 76, 176]))
2264 }
2265 None => panic!("Can't unwrap sockaddr storage"),
2266 }
2267 }
2268
2269 #[cfg(solarish)]
2270 #[test]
2271 fn solarish_tap() {
2272 let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176];
2273 let ptr = bytes.as_ptr();
2274 let sa = ptr as *const libc::sockaddr;
2275 let len = Some(bytes.len() as socklen_t);
2276 let _sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) };
2277
2278 assert!(_sock_addr.is_some());
2279
2280 let sock_addr = _sock_addr.unwrap();
2281
2282 assert_eq!(sock_addr.family().unwrap(), AddressFamily::Link);
2283
2284 assert_eq!(
2285 sock_addr.as_link_addr().unwrap().addr(),
2286 Some([24u8, 101, 144, 221, 76, 176])
2287 );
2288 }
2289
2290 #[test]
2291 fn size() {
2292 #[cfg(any(bsd, target_os = "aix", solarish, target_os = "haiku"))]
2293 let l = mem::size_of::<libc::sockaddr_dl>();
2294 #[cfg(any(linux_android, target_os = "fuchsia"))]
2295 let l = mem::size_of::<libc::sockaddr_ll>();
2296 assert_eq!(LinkAddr::size() as usize, l);
2297 }
2298 }
2299
2300 mod sockaddr_in {
2301 use super::*;
2302 use std::str::FromStr;
2303
2304 #[test]
2305 fn display() {
2306 let s = "127.0.0.1:8080";
2307 let addr = SockaddrIn::from_str(s).unwrap();
2308 assert_eq!(s, format!("{addr}"));
2309 }
2310
2311 #[test]
2312 fn size() {
2313 assert_eq!(
2314 mem::size_of::<libc::sockaddr_in>(),
2315 SockaddrIn::size() as usize
2316 );
2317 }
2318
2319 #[test]
2320 fn ip() {
2321 let s = "127.0.0.1:8082";
2322 let ip = SockaddrIn::from_str(s).unwrap().ip();
2323 assert_eq!("127.0.0.1", format!("{ip}"));
2324 }
2325 }
2326
2327 mod sockaddr_in6 {
2328 use super::*;
2329 use std::str::FromStr;
2330
2331 #[test]
2332 fn display() {
2333 let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
2334 let addr = SockaddrIn6::from_str(s).unwrap();
2335 assert_eq!(s, format!("{addr}"));
2336 }
2337
2338 #[test]
2339 fn size() {
2340 assert_eq!(
2341 mem::size_of::<libc::sockaddr_in6>(),
2342 SockaddrIn6::size() as usize
2343 );
2344 }
2345
2346 #[test]
2347 fn ip() {
2348 let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
2349 let ip = SockaddrIn6::from_str(s).unwrap().ip();
2350 assert_eq!("1234:5678:90ab:cdef::1111:2222", format!("{ip}"));
2351 }
2352
2353 #[test]
2354 fn to_and_from() {
2356 let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
2357 let mut nix_sin6 = SockaddrIn6::from_str(s).unwrap();
2358 nix_sin6.0.sin6_flowinfo = 0x12345678;
2359 nix_sin6.0.sin6_scope_id = 0x9abcdef0;
2360
2361 let std_sin6: std::net::SocketAddrV6 = nix_sin6.into();
2362 assert_eq!(nix_sin6, std_sin6.into());
2363 }
2364 }
2365
2366 mod sockaddr_storage {
2367 use super::*;
2368
2369 #[test]
2370 fn from_sockaddr_un_named() {
2371 let ua = UnixAddr::new("/var/run/mysock").unwrap();
2372 let ptr = ua.as_ptr().cast();
2373 let ss = unsafe { SockaddrStorage::from_raw(ptr, Some(ua.len())) }
2374 .unwrap();
2375 assert_eq!(ss.len(), ua.len());
2376 }
2377
2378 #[cfg(linux_android)]
2379 #[test]
2380 fn from_sockaddr_un_abstract_named() {
2381 let name = String::from("nix\0abstract\0test");
2382 let ua = UnixAddr::new_abstract(name.as_bytes()).unwrap();
2383 let ptr = ua.as_ptr().cast();
2384 let ss = unsafe { SockaddrStorage::from_raw(ptr, Some(ua.len())) }
2385 .unwrap();
2386 assert_eq!(ss.len(), ua.len());
2387 }
2388
2389 #[cfg(linux_android)]
2390 #[test]
2391 fn from_sockaddr_un_abstract_unnamed() {
2392 let ua = UnixAddr::new_unnamed();
2393 let ptr = ua.as_ptr().cast();
2394 let ss = unsafe { SockaddrStorage::from_raw(ptr, Some(ua.len())) }
2395 .unwrap();
2396 assert_eq!(ss.len(), ua.len());
2397 }
2398 }
2399
2400 mod unixaddr {
2401 use super::*;
2402
2403 #[cfg(linux_android)]
2404 #[test]
2405 fn abstract_sun_path() {
2406 let name = String::from("nix\0abstract\0test");
2407 let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
2408
2409 let sun_path1 =
2410 unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] };
2411 let sun_path2 = [
2412 0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0,
2413 116, 101, 115, 116,
2414 ];
2415 assert_eq!(sun_path1, sun_path2);
2416 }
2417
2418 #[test]
2419 fn size() {
2420 assert_eq!(
2421 mem::size_of::<libc::sockaddr_un>(),
2422 UnixAddr::size() as usize
2423 );
2424 }
2425 }
2426}