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