rustix/backend/linux_raw/net/
read_sockaddr.rs
1#![allow(unsafe_code)]
4
5use crate::backend::c;
6use crate::io::Errno;
7use crate::net::addr::SocketAddrLen;
8use crate::net::netlink::SocketAddrNetlink;
9#[cfg(target_os = "linux")]
10use crate::net::xdp::{SocketAddrXdp, SocketAddrXdpFlags};
11use crate::net::{
12 AddressFamily, Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6,
13};
14use core::mem::size_of;
15use core::slice;
16
17#[repr(C)]
19pub(crate) struct sockaddr_header {
20 sa_family: u16,
21}
22
23#[inline]
29pub(crate) const unsafe fn read_sa_family(storage: *const c::sockaddr) -> u16 {
30 let _ = c::sockaddr {
32 __storage: c::sockaddr_storage {
33 __bindgen_anon_1: linux_raw_sys::net::__kernel_sockaddr_storage__bindgen_ty_1 {
34 __bindgen_anon_1:
35 linux_raw_sys::net::__kernel_sockaddr_storage__bindgen_ty_1__bindgen_ty_1 {
36 ss_family: 0_u16,
37 __data: [0; 126_usize],
38 },
39 },
40 },
41 };
42
43 (*storage.cast::<sockaddr_header>()).sa_family
44}
45
46#[inline]
53pub(crate) unsafe fn initialize_family_to_unspec(storage: *mut c::sockaddr) {
54 (*storage.cast::<sockaddr_header>()).sa_family = c::AF_UNSPEC as _;
55}
56
57#[inline]
59pub(crate) unsafe fn sockaddr_nonempty(_storage: *const c::sockaddr, len: SocketAddrLen) -> bool {
60 len != 0
61}
62
63#[inline]
64pub(crate) fn read_sockaddr_v4(addr: &SocketAddrAny) -> Result<SocketAddrV4, Errno> {
65 if addr.address_family() != AddressFamily::INET {
66 return Err(Errno::AFNOSUPPORT);
67 }
68 assert!(addr.addr_len() as usize >= size_of::<c::sockaddr_in>());
69 let decode = unsafe { &*addr.as_ptr().cast::<c::sockaddr_in>() };
70 Ok(SocketAddrV4::new(
71 Ipv4Addr::from(u32::from_be(decode.sin_addr.s_addr)),
72 u16::from_be(decode.sin_port),
73 ))
74}
75
76#[inline]
77pub(crate) fn read_sockaddr_v6(addr: &SocketAddrAny) -> Result<SocketAddrV6, Errno> {
78 if addr.address_family() != AddressFamily::INET6 {
79 return Err(Errno::AFNOSUPPORT);
80 }
81 assert!(addr.addr_len() as usize >= size_of::<c::sockaddr_in6>());
82 let decode = unsafe { &*addr.as_ptr().cast::<c::sockaddr_in6>() };
83 Ok(SocketAddrV6::new(
84 Ipv6Addr::from(unsafe { decode.sin6_addr.in6_u.u6_addr8 }),
85 u16::from_be(decode.sin6_port),
86 u32::from_be(decode.sin6_flowinfo),
87 decode.sin6_scope_id,
88 ))
89}
90
91#[inline]
92pub(crate) fn read_sockaddr_unix(addr: &SocketAddrAny) -> Result<SocketAddrUnix, Errno> {
93 if addr.address_family() != AddressFamily::UNIX {
94 return Err(Errno::AFNOSUPPORT);
95 }
96 let offsetof_sun_path = super::addr::offsetof_sun_path();
97 let len = addr.addr_len() as usize;
98
99 assert!(len >= offsetof_sun_path);
100
101 if len == offsetof_sun_path {
102 SocketAddrUnix::new(&[][..])
103 } else {
104 let decode = unsafe { &*addr.as_ptr().cast::<c::sockaddr_un>() };
105
106 if decode.sun_path[0] == 0 {
110 let bytes = &decode.sun_path[1..len - offsetof_sun_path];
111
112 let bytes = unsafe { slice::from_raw_parts(bytes.as_ptr().cast::<u8>(), bytes.len()) };
114
115 return SocketAddrUnix::new_abstract_name(bytes);
116 }
117
118 let bytes = &decode.sun_path[..len - 1 - offsetof_sun_path];
120
121 let bytes = unsafe { slice::from_raw_parts(bytes.as_ptr().cast::<u8>(), bytes.len()) };
123
124 assert_eq!(decode.sun_path[len - 1 - offsetof_sun_path], 0);
125 SocketAddrUnix::new(bytes)
126 }
127}
128
129#[inline]
130pub(crate) fn read_sockaddr_xdp(addr: &SocketAddrAny) -> Result<SocketAddrXdp, Errno> {
131 if addr.address_family() != AddressFamily::XDP {
132 return Err(Errno::AFNOSUPPORT);
133 }
134 assert!(addr.addr_len() as usize >= size_of::<c::sockaddr_xdp>());
135 let decode = unsafe { &*addr.as_ptr().cast::<c::sockaddr_xdp>() };
136
137 Ok(SocketAddrXdp::new(
141 SocketAddrXdpFlags::from_bits_retain(decode.sxdp_flags),
142 u32::from_be(decode.sxdp_ifindex),
143 u32::from_be(decode.sxdp_queue_id),
144 ))
145}
146
147#[inline]
148pub(crate) fn read_sockaddr_netlink(addr: &SocketAddrAny) -> Result<SocketAddrNetlink, Errno> {
149 if addr.address_family() != AddressFamily::NETLINK {
150 return Err(Errno::AFNOSUPPORT);
151 }
152 assert!(addr.addr_len() as usize >= size_of::<c::sockaddr_nl>());
153 let decode = unsafe { &*addr.as_ptr().cast::<c::sockaddr_nl>() };
154 Ok(SocketAddrNetlink::new(decode.nl_pid, decode.nl_groups))
155}