rustix/backend/libc/net/
read_sockaddr.rs1#[cfg(unix)]
5use super::addr::SocketAddrUnix;
6use super::ext::{in6_addr_s6_addr, in_addr_s_addr, sockaddr_in6_sin6_scope_id};
7use crate::backend::c;
8#[cfg(not(windows))]
9use crate::ffi::CStr;
10use crate::io::Errno;
11use crate::net::addr::SocketAddrLen;
12#[cfg(linux_kernel)]
13use crate::net::netlink::SocketAddrNetlink;
14#[cfg(target_os = "linux")]
15use crate::net::xdp::{SocketAddrXdp, SocketAddrXdpFlags};
16use crate::net::{AddressFamily, Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrV4, SocketAddrV6};
17use core::mem::size_of;
18
19#[repr(C)]
21pub(crate) struct sockaddr_header {
22 #[cfg(any(
23 bsd,
24 target_os = "aix",
25 target_os = "espidf",
26 target_os = "haiku",
27 target_os = "nto",
28 target_os = "vita"
29 ))]
30 sa_len: u8,
31 #[cfg(any(
32 bsd,
33 target_os = "aix",
34 target_os = "espidf",
35 target_os = "haiku",
36 target_os = "nto",
37 target_os = "vita"
38 ))]
39 sa_family: u8,
40 #[cfg(not(any(
41 bsd,
42 target_os = "aix",
43 target_os = "espidf",
44 target_os = "haiku",
45 target_os = "nto",
46 target_os = "vita"
47 )))]
48 sa_family: u16,
49}
50
51#[inline]
57pub(crate) unsafe fn read_sa_family(storage: *const c::sockaddr) -> u16 {
58 let _ = c::sockaddr {
60 #[cfg(any(
61 bsd,
62 target_os = "aix",
63 target_os = "espidf",
64 target_os = "haiku",
65 target_os = "hurd",
66 target_os = "nto",
67 target_os = "vita"
68 ))]
69 sa_len: 0_u8,
70 #[cfg(any(
71 bsd,
72 target_os = "aix",
73 target_os = "espidf",
74 target_os = "haiku",
75 target_os = "hurd",
76 target_os = "nto",
77 target_os = "vita"
78 ))]
79 sa_family: 0_u8,
80 #[cfg(not(any(
81 bsd,
82 target_os = "aix",
83 target_os = "espidf",
84 target_os = "haiku",
85 target_os = "hurd",
86 target_os = "nto",
87 target_os = "vita"
88 )))]
89 sa_family: 0_u16,
90 #[cfg(not(any(target_os = "haiku", target_os = "horizon")))]
91 sa_data: [0; 14],
92 #[cfg(target_os = "horizon")]
93 sa_data: [0; 26],
94 #[cfg(target_os = "haiku")]
95 sa_data: [0; 30],
96 };
97
98 (*storage.cast::<sockaddr_header>()).sa_family.into()
99}
100
101#[cfg(apple)]
104#[inline]
105unsafe fn read_sun_path0(storage: *const c::sockaddr) -> u8 {
106 storage
108 .cast::<u8>()
109 .add(super::addr::offsetof_sun_path())
110 .read()
111}
112
113#[inline]
119pub(crate) unsafe fn sockaddr_nonempty(storage: *const c::sockaddr, len: SocketAddrLen) -> bool {
120 if len == 0 {
121 return false;
122 }
123
124 assert!(len as usize >= size_of::<c::sa_family_t>());
125 let family: c::c_int = read_sa_family(storage.cast::<c::sockaddr>()).into();
126 if family == c::AF_UNSPEC {
127 return false;
128 }
129
130 #[cfg(apple)]
133 if family == c::AF_UNIX && read_sun_path0(storage) == 0 {
134 return false;
135 }
136
137 true
138}
139
140pub(crate) unsafe fn initialize_family_to_unspec(storage: *mut c::sockaddr) {
147 (*storage.cast::<sockaddr_header>()).sa_family = c::AF_UNSPEC as _;
148}
149
150#[inline]
151pub(crate) fn read_sockaddr_v4(addr: &SocketAddrAny) -> Result<SocketAddrV4, Errno> {
152 if addr.address_family() != AddressFamily::INET {
153 return Err(Errno::AFNOSUPPORT);
154 }
155 assert!(addr.addr_len() as usize >= size_of::<c::sockaddr_in>());
156 let decode = unsafe { &*addr.as_ptr().cast::<c::sockaddr_in>() };
157 Ok(SocketAddrV4::new(
158 Ipv4Addr::from(u32::from_be(in_addr_s_addr(decode.sin_addr))),
159 u16::from_be(decode.sin_port),
160 ))
161}
162
163#[inline]
164pub(crate) fn read_sockaddr_v6(addr: &SocketAddrAny) -> Result<SocketAddrV6, Errno> {
165 if addr.address_family() != AddressFamily::INET6 {
166 return Err(Errno::AFNOSUPPORT);
167 }
168 assert!(addr.addr_len() as usize >= size_of::<c::sockaddr_in6>());
169 let decode = unsafe { &*addr.as_ptr().cast::<c::sockaddr_in6>() };
170 Ok(SocketAddrV6::new(
171 Ipv6Addr::from(in6_addr_s6_addr(decode.sin6_addr)),
172 u16::from_be(decode.sin6_port),
173 u32::from_be(decode.sin6_flowinfo),
174 sockaddr_in6_sin6_scope_id(decode),
175 ))
176}
177
178#[cfg(unix)]
179#[inline]
180pub(crate) fn read_sockaddr_unix(addr: &SocketAddrAny) -> Result<SocketAddrUnix, Errno> {
181 if addr.address_family() != AddressFamily::UNIX {
182 return Err(Errno::AFNOSUPPORT);
183 }
184
185 let offsetof_sun_path = super::addr::offsetof_sun_path();
186 let len = addr.addr_len() as usize;
187
188 assert!(len >= offsetof_sun_path);
189
190 if len == offsetof_sun_path {
191 SocketAddrUnix::new(&[][..])
192 } else {
193 let decode = unsafe { &*addr.as_ptr().cast::<c::sockaddr_un>() };
194
195 #[cfg(linux_kernel)]
199 if decode.sun_path[0] == 0 {
200 let name = &decode.sun_path[1..len - offsetof_sun_path];
201 let name = unsafe { core::mem::transmute::<&[c::c_char], &[u8]>(name) };
202 return SocketAddrUnix::new_abstract_name(name);
203 }
204
205 let path_bytes = if cfg!(any(solarish, target_os = "freebsd")) {
209 &decode.sun_path[..decode
213 .sun_path
214 .iter()
215 .position(|b| *b == 0)
216 .ok_or(Errno::INVAL)?]
217 } else {
218 let provided_len = len - 1 - offsetof_sun_path;
220 if decode.sun_path[provided_len] != 0 {
221 return Err(Errno::INVAL);
222 }
223 debug_assert_eq!(
224 unsafe { CStr::from_ptr(decode.sun_path.as_ptr().cast()) }
225 .to_bytes()
226 .len(),
227 provided_len
228 );
229 &decode.sun_path[..provided_len]
230 };
231
232 SocketAddrUnix::new(unsafe { core::mem::transmute::<&[c::c_char], &[u8]>(path_bytes) })
233 }
234}
235
236#[cfg(target_os = "linux")]
237#[inline]
238pub(crate) fn read_sockaddr_xdp(addr: &SocketAddrAny) -> Result<SocketAddrXdp, Errno> {
239 if addr.address_family() != AddressFamily::XDP {
240 return Err(Errno::AFNOSUPPORT);
241 }
242 assert!(addr.addr_len() as usize >= size_of::<c::sockaddr_xdp>());
243 let decode = unsafe { &*addr.as_ptr().cast::<c::sockaddr_xdp>() };
244
245 Ok(SocketAddrXdp::new(
249 SocketAddrXdpFlags::from_bits_retain(decode.sxdp_flags),
250 u32::from_be(decode.sxdp_ifindex),
251 u32::from_be(decode.sxdp_queue_id),
252 ))
253}
254
255#[cfg(linux_kernel)]
256#[inline]
257pub(crate) fn read_sockaddr_netlink(addr: &SocketAddrAny) -> Result<SocketAddrNetlink, Errno> {
258 if addr.address_family() != AddressFamily::NETLINK {
259 return Err(Errno::AFNOSUPPORT);
260 }
261 assert!(addr.addr_len() as usize >= size_of::<c::sockaddr_nl>());
262 let decode = unsafe { &*addr.as_ptr().cast::<c::sockaddr_nl>() };
263 Ok(SocketAddrNetlink::new(decode.nl_pid, decode.nl_groups))
264}