1 //! The BSD sockets API requires us to read the `ss_family` field before
2 //! we can interpret the rest of a `sockaddr` produced by the kernel.
3
4 use super::super::c;
5 use super::addr::SocketAddrStorage;
6 #[cfg(unix)]
7 use super::addr::SocketAddrUnix;
8 use super::ext::{in6_addr_new, in_addr_new, sockaddr_in6_new};
9 use crate::net::{SocketAddrAny, SocketAddrV4, SocketAddrV6};
10 use core::mem::size_of;
11
write_sockaddr( addr: &SocketAddrAny, storage: *mut SocketAddrStorage, ) -> usize12 pub(crate) unsafe fn write_sockaddr(
13 addr: &SocketAddrAny,
14 storage: *mut SocketAddrStorage,
15 ) -> usize {
16 match addr {
17 SocketAddrAny::V4(v4) => write_sockaddr_v4(v4, storage),
18 SocketAddrAny::V6(v6) => write_sockaddr_v6(v6, storage),
19 #[cfg(unix)]
20 SocketAddrAny::Unix(unix) => write_sockaddr_unix(unix, storage),
21 }
22 }
23
encode_sockaddr_v4(v4: &SocketAddrV4) -> c::sockaddr_in24 pub(crate) unsafe fn encode_sockaddr_v4(v4: &SocketAddrV4) -> c::sockaddr_in {
25 c::sockaddr_in {
26 #[cfg(any(
27 target_os = "dragonfly",
28 target_os = "freebsd",
29 target_os = "haiku",
30 target_os = "ios",
31 target_os = "macos",
32 target_os = "netbsd",
33 target_os = "openbsd",
34 ))]
35 sin_len: size_of::<c::sockaddr_in>() as _,
36 sin_family: c::AF_INET as _,
37 sin_port: u16::to_be(v4.port()),
38 sin_addr: in_addr_new(u32::from_ne_bytes(v4.ip().octets())),
39 #[cfg(not(target_os = "haiku"))]
40 sin_zero: [0; 8_usize],
41 #[cfg(target_os = "haiku")]
42 sin_zero: [0; 24_usize],
43 }
44 }
45
write_sockaddr_v4(v4: &SocketAddrV4, storage: *mut SocketAddrStorage) -> usize46 unsafe fn write_sockaddr_v4(v4: &SocketAddrV4, storage: *mut SocketAddrStorage) -> usize {
47 let encoded = encode_sockaddr_v4(v4);
48 core::ptr::write(storage.cast(), encoded);
49 size_of::<c::sockaddr_in>()
50 }
51
encode_sockaddr_v6(v6: &SocketAddrV6) -> c::sockaddr_in652 pub(crate) unsafe fn encode_sockaddr_v6(v6: &SocketAddrV6) -> c::sockaddr_in6 {
53 #[cfg(any(
54 target_os = "dragonfly",
55 target_os = "freebsd",
56 target_os = "haiku",
57 target_os = "ios",
58 target_os = "macos",
59 target_os = "netbsd",
60 target_os = "openbsd",
61 ))]
62 {
63 sockaddr_in6_new(
64 size_of::<c::sockaddr_in6>() as _,
65 c::AF_INET6 as _,
66 u16::to_be(v6.port()),
67 u32::to_be(v6.flowinfo()),
68 in6_addr_new(v6.ip().octets()),
69 v6.scope_id(),
70 )
71 }
72 #[cfg(not(any(
73 target_os = "dragonfly",
74 target_os = "freebsd",
75 target_os = "haiku",
76 target_os = "ios",
77 target_os = "macos",
78 target_os = "netbsd",
79 target_os = "openbsd",
80 )))]
81 {
82 sockaddr_in6_new(
83 c::AF_INET6 as _,
84 u16::to_be(v6.port()),
85 u32::to_be(v6.flowinfo()),
86 in6_addr_new(v6.ip().octets()),
87 v6.scope_id(),
88 )
89 }
90 }
91
write_sockaddr_v6(v6: &SocketAddrV6, storage: *mut SocketAddrStorage) -> usize92 unsafe fn write_sockaddr_v6(v6: &SocketAddrV6, storage: *mut SocketAddrStorage) -> usize {
93 let encoded = encode_sockaddr_v6(v6);
94 core::ptr::write(storage.cast(), encoded);
95 size_of::<c::sockaddr_in6>()
96 }
97
98 #[cfg(unix)]
write_sockaddr_unix(unix: &SocketAddrUnix, storage: *mut SocketAddrStorage) -> usize99 unsafe fn write_sockaddr_unix(unix: &SocketAddrUnix, storage: *mut SocketAddrStorage) -> usize {
100 core::ptr::write(storage.cast(), unix.unix);
101 unix.len()
102 }
103