1use crate::ptr::{UserConstPtr, UserPtr};
4use axerrno::{LinuxError, LinuxResult};
5use core::{
6 mem::{MaybeUninit, size_of},
7 net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
8};
9use linux_raw_sys::net::{
10 __kernel_sa_family_t, AF_INET, AF_INET6, in_addr, in6_addr, sockaddr, sockaddr_in,
11 sockaddr_in6, socklen_t,
12};
13
14pub trait SocketAddrExt: Sized {
17 fn read_from_user(addr: UserConstPtr<sockaddr>, addrlen: socklen_t) -> LinuxResult<Self>;
20
21 fn write_to_user(&self, addr: UserPtr<sockaddr>) -> LinuxResult<socklen_t>;
24
25 fn family(&self) -> u16;
27
28 fn addr_len(&self) -> socklen_t;
30}
31
32#[inline]
38fn copy_sockaddr_from_user(
39 addr: UserConstPtr<sockaddr>,
40 addrlen: socklen_t,
41) -> LinuxResult<MaybeUninit<sockaddr>> {
42 let mut storage = MaybeUninit::<sockaddr>::uninit();
43 let sock_addr = addr.get_as_ref()?;
44 unsafe {
45 core::ptr::copy_nonoverlapping(
46 sock_addr as *const sockaddr as *const u8,
47 storage.as_mut_ptr() as *mut u8,
48 addrlen as usize,
49 )
50 };
51 Ok(storage)
52}
53
54impl SocketAddrExt for SocketAddr {
55 fn read_from_user(addr: UserConstPtr<sockaddr>, addrlen: socklen_t) -> LinuxResult<Self> {
63 if size_of::<__kernel_sa_family_t>() > addrlen as usize
64 || addrlen as usize > size_of::<sockaddr>()
65 {
66 return Err(LinuxError::EINVAL);
67 }
68 let src_addr = addr.get_as_ref()?;
69 let family = unsafe {
70 src_addr
71 .__storage
72 .__bindgen_anon_1
73 .__bindgen_anon_1
74 .ss_family as u32
75 };
76 match family {
77 AF_INET => SocketAddrV4::read_from_user(addr, addrlen).map(SocketAddr::V4),
78 AF_INET6 => SocketAddrV6::read_from_user(addr, addrlen).map(SocketAddr::V6),
79 _ => Err(LinuxError::EAFNOSUPPORT),
80 }
81 }
82
83 fn write_to_user(&self, addr: UserPtr<sockaddr>) -> LinuxResult<socklen_t> {
89 if addr.is_null() {
90 return Err(LinuxError::EINVAL);
91 }
92
93 match self {
94 SocketAddr::V4(v4) => v4.write_to_user(addr),
95 SocketAddr::V6(v6) => v6.write_to_user(addr),
96 }
97 }
98
99 fn family(&self) -> u16 {
103 match self {
104 SocketAddr::V4(v4) => v4.family(),
105 SocketAddr::V6(v6) => v6.family(),
106 }
107 }
108
109 fn addr_len(&self) -> socklen_t {
114 match self {
115 SocketAddr::V4(v4) => v4.addr_len(),
116 SocketAddr::V6(v6) => v6.addr_len(),
117 }
118 }
119}
120
121impl SocketAddrExt for SocketAddrV4 {
122 fn read_from_user(addr: UserConstPtr<sockaddr>, addrlen: socklen_t) -> LinuxResult<Self> {
124 if addrlen < size_of::<sockaddr_in>() as socklen_t {
125 return Err(LinuxError::EINVAL);
126 }
127 let storage = copy_sockaddr_from_user(addr, addrlen)?;
128 let addr_in = unsafe { &*(storage.as_ptr() as *const sockaddr_in) };
129 if addr_in.sin_family as u32 != AF_INET {
130 return Err(LinuxError::EAFNOSUPPORT);
131 }
132
133 Ok(SocketAddrV4::new(
134 Ipv4Addr::from_bits(u32::from_be(addr_in.sin_addr.s_addr)),
135 u16::from_be(addr_in.sin_port),
136 ))
137 }
138
139 fn write_to_user(&self, addr: UserPtr<sockaddr>) -> LinuxResult<socklen_t> {
141 if addr.is_null() {
142 return Err(LinuxError::EINVAL);
143 }
144 let dst_addr = addr.get_as_mut()?;
145 let len = size_of::<sockaddr_in>() as socklen_t;
146 let sockin_addr = sockaddr_in {
147 sin_family: AF_INET as _,
148 sin_port: self.port().to_be(),
149 sin_addr: in_addr {
150 s_addr: u32::from_ne_bytes(self.ip().octets()),
151 },
152 __pad: [0_u8; 8],
153 };
154 unsafe {
155 core::ptr::copy_nonoverlapping(
156 &sockin_addr as *const sockaddr_in as *const u8,
157 dst_addr as *mut sockaddr as *mut u8,
158 len as usize,
159 )
160 };
161
162 Ok(len)
163 }
164
165 fn family(&self) -> u16 {
167 AF_INET as u16
168 }
169
170 fn addr_len(&self) -> socklen_t {
172 size_of::<sockaddr_in>() as socklen_t
173 }
174}
175
176impl SocketAddrExt for SocketAddrV6 {
177 fn read_from_user(addr: UserConstPtr<sockaddr>, addrlen: socklen_t) -> LinuxResult<Self> {
179 if addrlen < size_of::<sockaddr_in6>() as socklen_t {
180 return Err(LinuxError::EINVAL);
181 }
182 let storage = copy_sockaddr_from_user(addr, addrlen)?;
183 let addr_in6 = unsafe { &*(storage.as_ptr() as *const sockaddr_in6) };
184 if addr_in6.sin6_family as u32 != AF_INET6 {
185 return Err(LinuxError::EAFNOSUPPORT);
186 }
187
188 Ok(SocketAddrV6::new(
189 Ipv6Addr::from(unsafe { addr_in6.sin6_addr.in6_u.u6_addr8 }),
190 u16::from_be(addr_in6.sin6_port),
191 u32::from_be(addr_in6.sin6_flowinfo),
192 addr_in6.sin6_scope_id,
193 ))
194 }
195 fn write_to_user(&self, addr: UserPtr<sockaddr>) -> LinuxResult<socklen_t> {
197 if addr.is_null() {
198 return Err(LinuxError::EINVAL);
199 }
200 let dst_addr = addr.get_as_mut()?;
201 let len = size_of::<sockaddr_in6>() as socklen_t;
202 let sockin_addr = sockaddr_in6 {
203 sin6_family: AF_INET6 as _,
204 sin6_port: self.port().to_be(),
205 sin6_flowinfo: self.flowinfo().to_be(),
206 sin6_addr: in6_addr {
207 in6_u: linux_raw_sys::net::in6_addr__bindgen_ty_1 {
208 u6_addr8: self.ip().octets(),
209 },
210 },
211 sin6_scope_id: self.scope_id(),
212 };
213
214 unsafe {
215 core::ptr::copy_nonoverlapping(
216 &sockin_addr as *const sockaddr_in6 as *const u8,
217 dst_addr as *mut sockaddr as *mut u8,
218 len as usize,
219 )
220 };
221
222 Ok(len)
223 }
224
225 fn family(&self) -> u16 {
227 AF_INET6 as u16
228 }
229
230 fn addr_len(&self) -> socklen_t {
232 size_of::<sockaddr_in6>() as socklen_t
233 }
234}