1 | //! linux_raw syscalls supporting `rustix::net`. |
2 | //! |
3 | //! # Safety |
4 | //! |
5 | //! See the `rustix::backend` module documentation for details. |
6 | #![allow (unsafe_code, clippy::undocumented_unsafe_blocks)] |
7 | |
8 | #[cfg (target_os = "linux" )] |
9 | use super::msghdr::with_xdp_msghdr; |
10 | use super::msghdr::{ |
11 | with_noaddr_msghdr, with_recv_msghdr, with_unix_msghdr, with_v4_msghdr, with_v6_msghdr, |
12 | }; |
13 | use super::read_sockaddr::{initialize_family_to_unspec, maybe_read_sockaddr_os, read_sockaddr_os}; |
14 | use super::send_recv::{RecvFlags, SendFlags}; |
15 | #[cfg (target_os = "linux" )] |
16 | use super::write_sockaddr::encode_sockaddr_xdp; |
17 | use super::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6}; |
18 | use crate::backend::c; |
19 | use crate::backend::conv::{ |
20 | by_mut, by_ref, c_int, c_uint, pass_usize, ret, ret_owned_fd, ret_usize, size_of, slice, |
21 | socklen_t, zero, |
22 | }; |
23 | use crate::fd::{BorrowedFd, OwnedFd}; |
24 | use crate::io::{self, IoSlice, IoSliceMut}; |
25 | #[cfg (target_os = "linux" )] |
26 | use crate::net::xdp::SocketAddrXdp; |
27 | use crate::net::{ |
28 | AddressFamily, Protocol, RecvAncillaryBuffer, RecvMsgReturn, SendAncillaryBuffer, Shutdown, |
29 | SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6, SocketFlags, SocketType, |
30 | }; |
31 | use c::{sockaddr, sockaddr_in, sockaddr_in6, socklen_t}; |
32 | use core::mem::MaybeUninit; |
33 | #[cfg (target_arch = "x86" )] |
34 | use { |
35 | crate::backend::conv::{slice_just_addr, x86_sys}, |
36 | crate::backend::reg::{ArgReg, SocketArg}, |
37 | linux_raw_sys::net::{ |
38 | SYS_ACCEPT, SYS_ACCEPT4, SYS_BIND, SYS_CONNECT, SYS_GETPEERNAME, SYS_GETSOCKNAME, |
39 | SYS_LISTEN, SYS_RECV, SYS_RECVFROM, SYS_RECVMSG, SYS_SEND, SYS_SENDMSG, SYS_SENDTO, |
40 | SYS_SHUTDOWN, SYS_SOCKET, SYS_SOCKETPAIR, |
41 | }, |
42 | }; |
43 | |
44 | #[inline ] |
45 | pub(crate) fn socket( |
46 | family: AddressFamily, |
47 | type_: SocketType, |
48 | protocol: Option<Protocol>, |
49 | ) -> io::Result<OwnedFd> { |
50 | #[cfg (not(target_arch = "x86" ))] |
51 | unsafe { |
52 | ret_owned_fd(raw:syscall_readonly!(__NR_socket, family, type_, protocol)) |
53 | } |
54 | #[cfg (target_arch = "x86" )] |
55 | unsafe { |
56 | ret_owned_fd(syscall_readonly!( |
57 | __NR_socketcall, |
58 | x86_sys(SYS_SOCKET), |
59 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
60 | family.into(), |
61 | type_.into(), |
62 | protocol.into(), |
63 | ]) |
64 | )) |
65 | } |
66 | } |
67 | |
68 | #[inline ] |
69 | pub(crate) fn socket_with( |
70 | family: AddressFamily, |
71 | type_: SocketType, |
72 | flags: SocketFlags, |
73 | protocol: Option<Protocol>, |
74 | ) -> io::Result<OwnedFd> { |
75 | #[cfg (not(target_arch = "x86" ))] |
76 | unsafe { |
77 | ret_owned_fd(raw:syscall_readonly!( |
78 | __NR_socket, |
79 | family, |
80 | (type_, flags), |
81 | protocol |
82 | )) |
83 | } |
84 | #[cfg (target_arch = "x86" )] |
85 | unsafe { |
86 | ret_owned_fd(syscall_readonly!( |
87 | __NR_socketcall, |
88 | x86_sys(SYS_SOCKET), |
89 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
90 | family.into(), |
91 | (type_, flags).into(), |
92 | protocol.into(), |
93 | ]) |
94 | )) |
95 | } |
96 | } |
97 | |
98 | #[inline ] |
99 | pub(crate) fn socketpair( |
100 | family: AddressFamily, |
101 | type_: SocketType, |
102 | flags: SocketFlags, |
103 | protocol: Option<Protocol>, |
104 | ) -> io::Result<(OwnedFd, OwnedFd)> { |
105 | #[cfg (not(target_arch = "x86" ))] |
106 | unsafe { |
107 | let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit(); |
108 | ret(syscall!( |
109 | __NR_socketpair, |
110 | family, |
111 | (type_, flags), |
112 | protocol, |
113 | &mut result |
114 | ))?; |
115 | let [fd0, fd1] = result.assume_init(); |
116 | Ok((fd0, fd1)) |
117 | } |
118 | #[cfg (target_arch = "x86" )] |
119 | unsafe { |
120 | let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit(); |
121 | ret(syscall!( |
122 | __NR_socketcall, |
123 | x86_sys(SYS_SOCKETPAIR), |
124 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
125 | family.into(), |
126 | (type_, flags).into(), |
127 | protocol.into(), |
128 | (&mut result).into(), |
129 | ]) |
130 | ))?; |
131 | let [fd0, fd1] = result.assume_init(); |
132 | Ok((fd0, fd1)) |
133 | } |
134 | } |
135 | |
136 | #[inline ] |
137 | pub(crate) fn accept(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> { |
138 | #[cfg (not(any(target_arch = "x86" , target_arch = "s390x" )))] |
139 | unsafe { |
140 | let fd: OwnedFd = ret_owned_fd(raw:syscall_readonly!(__NR_accept, fd, zero(), zero()))?; |
141 | Ok(fd) |
142 | } |
143 | #[cfg (target_arch = "x86" )] |
144 | unsafe { |
145 | let fd = ret_owned_fd(syscall_readonly!( |
146 | __NR_socketcall, |
147 | x86_sys(SYS_ACCEPT), |
148 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), zero(), zero()]) |
149 | ))?; |
150 | Ok(fd) |
151 | } |
152 | #[cfg (target_arch = "s390x" )] |
153 | { |
154 | // accept is not available on s390x |
155 | accept_with(fd, SocketFlags::empty()) |
156 | } |
157 | } |
158 | |
159 | #[inline ] |
160 | pub(crate) fn accept_with(fd: BorrowedFd<'_>, flags: SocketFlags) -> io::Result<OwnedFd> { |
161 | #[cfg (not(target_arch = "x86" ))] |
162 | unsafe { |
163 | let fd: OwnedFd = ret_owned_fd(raw:syscall_readonly!(__NR_accept4, fd, zero(), zero(), flags))?; |
164 | Ok(fd) |
165 | } |
166 | #[cfg (target_arch = "x86" )] |
167 | unsafe { |
168 | let fd = ret_owned_fd(syscall_readonly!( |
169 | __NR_socketcall, |
170 | x86_sys(SYS_ACCEPT4), |
171 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), zero(), zero(), flags.into()]) |
172 | ))?; |
173 | Ok(fd) |
174 | } |
175 | } |
176 | |
177 | #[inline ] |
178 | pub(crate) fn acceptfrom(fd: BorrowedFd<'_>) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> { |
179 | #[cfg (not(any(target_arch = "x86" , target_arch = "s390x" )))] |
180 | unsafe { |
181 | let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t; |
182 | let mut storage = MaybeUninit::<sockaddr>::uninit(); |
183 | let fd = ret_owned_fd(syscall!( |
184 | __NR_accept, |
185 | fd, |
186 | &mut storage, |
187 | by_mut(&mut addrlen) |
188 | ))?; |
189 | Ok(( |
190 | fd, |
191 | maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()), |
192 | )) |
193 | } |
194 | #[cfg (target_arch = "x86" )] |
195 | unsafe { |
196 | let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t; |
197 | let mut storage = MaybeUninit::<sockaddr>::uninit(); |
198 | let fd = ret_owned_fd(syscall!( |
199 | __NR_socketcall, |
200 | x86_sys(SYS_ACCEPT), |
201 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
202 | fd.into(), |
203 | (&mut storage).into(), |
204 | by_mut(&mut addrlen), |
205 | ]) |
206 | ))?; |
207 | Ok(( |
208 | fd, |
209 | maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()), |
210 | )) |
211 | } |
212 | #[cfg (target_arch = "s390x" )] |
213 | { |
214 | // accept is not available on s390x |
215 | acceptfrom_with(fd, SocketFlags::empty()) |
216 | } |
217 | } |
218 | |
219 | #[inline ] |
220 | pub(crate) fn acceptfrom_with( |
221 | fd: BorrowedFd<'_>, |
222 | flags: SocketFlags, |
223 | ) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> { |
224 | #[cfg (not(target_arch = "x86" ))] |
225 | unsafe { |
226 | let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t; |
227 | let mut storage = MaybeUninit::<sockaddr>::uninit(); |
228 | let fd = ret_owned_fd(syscall!( |
229 | __NR_accept4, |
230 | fd, |
231 | &mut storage, |
232 | by_mut(&mut addrlen), |
233 | flags |
234 | ))?; |
235 | Ok(( |
236 | fd, |
237 | maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()), |
238 | )) |
239 | } |
240 | #[cfg (target_arch = "x86" )] |
241 | unsafe { |
242 | let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t; |
243 | let mut storage = MaybeUninit::<sockaddr>::uninit(); |
244 | let fd = ret_owned_fd(syscall!( |
245 | __NR_socketcall, |
246 | x86_sys(SYS_ACCEPT4), |
247 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
248 | fd.into(), |
249 | (&mut storage).into(), |
250 | by_mut(&mut addrlen), |
251 | flags.into(), |
252 | ]) |
253 | ))?; |
254 | Ok(( |
255 | fd, |
256 | maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()), |
257 | )) |
258 | } |
259 | } |
260 | |
261 | #[inline ] |
262 | pub(crate) fn recvmsg( |
263 | sockfd: BorrowedFd<'_>, |
264 | iov: &mut [IoSliceMut<'_>], |
265 | control: &mut RecvAncillaryBuffer<'_>, |
266 | msg_flags: RecvFlags, |
267 | ) -> io::Result<RecvMsgReturn> { |
268 | let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit(); |
269 | |
270 | with_recv_msghdr(&mut storage, iov, control, |msghdr| { |
271 | #[cfg (not(target_arch = "x86" ))] |
272 | let result = |
273 | unsafe { ret_usize(syscall!(__NR_recvmsg, sockfd, by_mut(msghdr), msg_flags)) }; |
274 | |
275 | #[cfg (target_arch = "x86" )] |
276 | let result = unsafe { |
277 | ret_usize(syscall!( |
278 | __NR_socketcall, |
279 | x86_sys(SYS_RECVMSG), |
280 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
281 | sockfd.into(), |
282 | by_mut(msghdr), |
283 | msg_flags.into(), |
284 | ]) |
285 | )) |
286 | }; |
287 | |
288 | result.map(|bytes| { |
289 | // Get the address of the sender, if any. |
290 | let addr = |
291 | unsafe { maybe_read_sockaddr_os(msghdr.msg_name as _, msghdr.msg_namelen as _) }; |
292 | |
293 | RecvMsgReturn { |
294 | bytes, |
295 | address: addr, |
296 | flags: RecvFlags::from_bits_retain(msghdr.msg_flags), |
297 | } |
298 | }) |
299 | }) |
300 | } |
301 | |
302 | #[inline ] |
303 | pub(crate) fn sendmsg( |
304 | sockfd: BorrowedFd<'_>, |
305 | iov: &[IoSlice<'_>], |
306 | control: &mut SendAncillaryBuffer<'_, '_, '_>, |
307 | msg_flags: SendFlags, |
308 | ) -> io::Result<usize> { |
309 | with_noaddr_msghdr(iov, control, |msghdr: msghdr| { |
310 | #[cfg (not(target_arch = "x86" ))] |
311 | let result: Result = |
312 | unsafe { ret_usize(raw:syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) }; |
313 | |
314 | #[cfg (target_arch = "x86" )] |
315 | let result = unsafe { |
316 | ret_usize(syscall!( |
317 | __NR_socketcall, |
318 | x86_sys(SYS_SENDMSG), |
319 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
320 | sockfd.into(), |
321 | by_ref(&msghdr), |
322 | msg_flags.into() |
323 | ]) |
324 | )) |
325 | }; |
326 | |
327 | result |
328 | }) |
329 | } |
330 | |
331 | #[inline ] |
332 | pub(crate) fn sendmsg_v4( |
333 | sockfd: BorrowedFd<'_>, |
334 | addr: &SocketAddrV4, |
335 | iov: &[IoSlice<'_>], |
336 | control: &mut SendAncillaryBuffer<'_, '_, '_>, |
337 | msg_flags: SendFlags, |
338 | ) -> io::Result<usize> { |
339 | with_v4_msghdr(addr, iov, control, |msghdr: msghdr| { |
340 | #[cfg (not(target_arch = "x86" ))] |
341 | let result: Result = |
342 | unsafe { ret_usize(raw:syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) }; |
343 | |
344 | #[cfg (target_arch = "x86" )] |
345 | let result = unsafe { |
346 | ret_usize(syscall!( |
347 | __NR_socketcall, |
348 | x86_sys(SYS_SENDMSG), |
349 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
350 | sockfd.into(), |
351 | by_ref(&msghdr), |
352 | msg_flags.into(), |
353 | ]) |
354 | )) |
355 | }; |
356 | |
357 | result |
358 | }) |
359 | } |
360 | |
361 | #[inline ] |
362 | pub(crate) fn sendmsg_v6( |
363 | sockfd: BorrowedFd<'_>, |
364 | addr: &SocketAddrV6, |
365 | iov: &[IoSlice<'_>], |
366 | control: &mut SendAncillaryBuffer<'_, '_, '_>, |
367 | msg_flags: SendFlags, |
368 | ) -> io::Result<usize> { |
369 | with_v6_msghdr(addr, iov, control, |msghdr: msghdr| { |
370 | #[cfg (not(target_arch = "x86" ))] |
371 | let result: Result = |
372 | unsafe { ret_usize(raw:syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) }; |
373 | |
374 | #[cfg (target_arch = "x86" )] |
375 | let result = unsafe { |
376 | ret_usize(syscall!( |
377 | __NR_socketcall, |
378 | x86_sys(SYS_SENDMSG), |
379 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
380 | sockfd.into(), |
381 | by_ref(&msghdr), |
382 | msg_flags.into() |
383 | ]) |
384 | )) |
385 | }; |
386 | |
387 | result |
388 | }) |
389 | } |
390 | |
391 | #[inline ] |
392 | pub(crate) fn sendmsg_unix( |
393 | sockfd: BorrowedFd<'_>, |
394 | addr: &SocketAddrUnix, |
395 | iov: &[IoSlice<'_>], |
396 | control: &mut SendAncillaryBuffer<'_, '_, '_>, |
397 | msg_flags: SendFlags, |
398 | ) -> io::Result<usize> { |
399 | with_unix_msghdr(addr, iov, control, |msghdr: msghdr| { |
400 | #[cfg (not(target_arch = "x86" ))] |
401 | let result: Result = |
402 | unsafe { ret_usize(raw:syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) }; |
403 | |
404 | #[cfg (target_arch = "x86" )] |
405 | let result = unsafe { |
406 | ret_usize(syscall!( |
407 | __NR_socketcall, |
408 | x86_sys(SYS_SENDMSG), |
409 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
410 | sockfd.into(), |
411 | by_ref(&msghdr), |
412 | msg_flags.into() |
413 | ]) |
414 | )) |
415 | }; |
416 | |
417 | result |
418 | }) |
419 | } |
420 | |
421 | #[cfg (target_os = "linux" )] |
422 | #[inline ] |
423 | pub(crate) fn sendmsg_xdp( |
424 | sockfd: BorrowedFd<'_>, |
425 | addr: &SocketAddrXdp, |
426 | iov: &[IoSlice<'_>], |
427 | control: &mut SendAncillaryBuffer<'_, '_, '_>, |
428 | msg_flags: SendFlags, |
429 | ) -> io::Result<usize> { |
430 | with_xdp_msghdr(addr, iov, control, |msghdr: msghdr| { |
431 | #[cfg (not(target_arch = "x86" ))] |
432 | let result: Result = |
433 | unsafe { ret_usize(raw:syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) }; |
434 | |
435 | #[cfg (target_arch = "x86" )] |
436 | let result = unsafe { |
437 | ret_usize(syscall!( |
438 | __NR_socketcall, |
439 | x86_sys(SYS_SENDMSG), |
440 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
441 | sockfd.into(), |
442 | by_ref(&msghdr), |
443 | msg_flags.into() |
444 | ]) |
445 | )) |
446 | }; |
447 | |
448 | result |
449 | }) |
450 | } |
451 | |
452 | #[inline ] |
453 | pub(crate) fn shutdown(fd: BorrowedFd<'_>, how: Shutdown) -> io::Result<()> { |
454 | #[cfg (not(target_arch = "x86" ))] |
455 | unsafe { |
456 | ret(raw:syscall_readonly!( |
457 | __NR_shutdown, |
458 | fd, |
459 | c_uint(how as c::c_uint) |
460 | )) |
461 | } |
462 | #[cfg (target_arch = "x86" )] |
463 | unsafe { |
464 | ret(syscall_readonly!( |
465 | __NR_socketcall, |
466 | x86_sys(SYS_SHUTDOWN), |
467 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), c_uint(how as c::c_uint)]) |
468 | )) |
469 | } |
470 | } |
471 | |
472 | #[inline ] |
473 | pub(crate) fn send(fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags) -> io::Result<usize> { |
474 | let (buf_addr, buf_len) = slice(buf); |
475 | |
476 | #[cfg (not(any( |
477 | target_arch = "aarch64" , |
478 | target_arch = "mips64" , |
479 | target_arch = "mips64r6" , |
480 | target_arch = "riscv64" , |
481 | target_arch = "s390x" , |
482 | target_arch = "x86" , |
483 | target_arch = "x86_64" , |
484 | )))] |
485 | unsafe { |
486 | ret_usize(syscall_readonly!(__NR_send, fd, buf_addr, buf_len, flags)) |
487 | } |
488 | #[cfg (any( |
489 | target_arch = "aarch64" , |
490 | target_arch = "mips64" , |
491 | target_arch = "mips64r6" , |
492 | target_arch = "riscv64" , |
493 | target_arch = "s390x" , |
494 | target_arch = "x86_64" , |
495 | ))] |
496 | unsafe { |
497 | ret_usize(syscall_readonly!( |
498 | __NR_sendto, |
499 | fd, |
500 | buf_addr, |
501 | buf_len, |
502 | flags, |
503 | zero(), |
504 | zero() |
505 | )) |
506 | } |
507 | #[cfg (target_arch = "x86" )] |
508 | unsafe { |
509 | ret_usize(syscall_readonly!( |
510 | __NR_socketcall, |
511 | x86_sys(SYS_SEND), |
512 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
513 | fd.into(), |
514 | buf_addr, |
515 | buf_len, |
516 | flags.into() |
517 | ]) |
518 | )) |
519 | } |
520 | } |
521 | |
522 | #[inline ] |
523 | pub(crate) fn sendto_v4( |
524 | fd: BorrowedFd<'_>, |
525 | buf: &[u8], |
526 | flags: SendFlags, |
527 | addr: &SocketAddrV4, |
528 | ) -> io::Result<usize> { |
529 | let (buf_addr, buf_len) = slice(buf); |
530 | |
531 | #[cfg (not(target_arch = "x86" ))] |
532 | unsafe { |
533 | ret_usize(syscall_readonly!( |
534 | __NR_sendto, |
535 | fd, |
536 | buf_addr, |
537 | buf_len, |
538 | flags, |
539 | by_ref(&encode_sockaddr_v4(addr)), |
540 | size_of::<sockaddr_in, _>() |
541 | )) |
542 | } |
543 | #[cfg (target_arch = "x86" )] |
544 | unsafe { |
545 | ret_usize(syscall_readonly!( |
546 | __NR_socketcall, |
547 | x86_sys(SYS_SENDTO), |
548 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
549 | fd.into(), |
550 | buf_addr, |
551 | buf_len, |
552 | flags.into(), |
553 | by_ref(&encode_sockaddr_v4(addr)), |
554 | size_of::<sockaddr_in, _>(), |
555 | ]) |
556 | )) |
557 | } |
558 | } |
559 | |
560 | #[inline ] |
561 | pub(crate) fn sendto_v6( |
562 | fd: BorrowedFd<'_>, |
563 | buf: &[u8], |
564 | flags: SendFlags, |
565 | addr: &SocketAddrV6, |
566 | ) -> io::Result<usize> { |
567 | let (buf_addr, buf_len) = slice(buf); |
568 | |
569 | #[cfg (not(target_arch = "x86" ))] |
570 | unsafe { |
571 | ret_usize(syscall_readonly!( |
572 | __NR_sendto, |
573 | fd, |
574 | buf_addr, |
575 | buf_len, |
576 | flags, |
577 | by_ref(&encode_sockaddr_v6(addr)), |
578 | size_of::<sockaddr_in6, _>() |
579 | )) |
580 | } |
581 | #[cfg (target_arch = "x86" )] |
582 | unsafe { |
583 | ret_usize(syscall_readonly!( |
584 | __NR_socketcall, |
585 | x86_sys(SYS_SENDTO), |
586 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
587 | fd.into(), |
588 | buf_addr, |
589 | buf_len, |
590 | flags.into(), |
591 | by_ref(&encode_sockaddr_v6(addr)), |
592 | size_of::<sockaddr_in6, _>(), |
593 | ]) |
594 | )) |
595 | } |
596 | } |
597 | |
598 | #[inline ] |
599 | pub(crate) fn sendto_unix( |
600 | fd: BorrowedFd<'_>, |
601 | buf: &[u8], |
602 | flags: SendFlags, |
603 | addr: &SocketAddrUnix, |
604 | ) -> io::Result<usize> { |
605 | let (buf_addr, buf_len) = slice(buf); |
606 | |
607 | #[cfg (not(target_arch = "x86" ))] |
608 | unsafe { |
609 | ret_usize(syscall_readonly!( |
610 | __NR_sendto, |
611 | fd, |
612 | buf_addr, |
613 | buf_len, |
614 | flags, |
615 | by_ref(&addr.unix), |
616 | socklen_t(addr.addr_len()) |
617 | )) |
618 | } |
619 | #[cfg (target_arch = "x86" )] |
620 | unsafe { |
621 | ret_usize(syscall_readonly!( |
622 | __NR_socketcall, |
623 | x86_sys(SYS_SENDTO), |
624 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
625 | fd.into(), |
626 | buf_addr, |
627 | buf_len, |
628 | flags.into(), |
629 | by_ref(&addr.unix), |
630 | socklen_t(addr.addr_len()), |
631 | ]) |
632 | )) |
633 | } |
634 | } |
635 | |
636 | #[cfg (target_os = "linux" )] |
637 | #[inline ] |
638 | pub(crate) fn sendto_xdp( |
639 | fd: BorrowedFd<'_>, |
640 | buf: &[u8], |
641 | flags: SendFlags, |
642 | addr: &SocketAddrXdp, |
643 | ) -> io::Result<usize> { |
644 | let (buf_addr, buf_len) = slice(buf); |
645 | |
646 | #[cfg (not(target_arch = "x86" ))] |
647 | unsafe { |
648 | ret_usize(syscall_readonly!( |
649 | __NR_sendto, |
650 | fd, |
651 | buf_addr, |
652 | buf_len, |
653 | flags, |
654 | by_ref(&encode_sockaddr_xdp(addr)), |
655 | size_of::<c::sockaddr_xdp, _>() |
656 | )) |
657 | } |
658 | #[cfg (target_arch = "x86" )] |
659 | unsafe { |
660 | ret_usize(syscall_readonly!( |
661 | __NR_socketcall, |
662 | x86_sys(SYS_SENDTO), |
663 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
664 | fd.into(), |
665 | buf_addr, |
666 | buf_len, |
667 | flags.into(), |
668 | by_ref(&encode_sockaddr_xdp(addr)), |
669 | size_of::<c::sockaddr_xdp, _>(), |
670 | ]) |
671 | )) |
672 | } |
673 | } |
674 | |
675 | #[inline ] |
676 | pub(crate) unsafe fn recv( |
677 | fd: BorrowedFd<'_>, |
678 | buf: *mut u8, |
679 | len: usize, |
680 | flags: RecvFlags, |
681 | ) -> io::Result<usize> { |
682 | #[cfg (not(any( |
683 | target_arch = "aarch64" , |
684 | target_arch = "mips64" , |
685 | target_arch = "mips64r6" , |
686 | target_arch = "riscv64" , |
687 | target_arch = "s390x" , |
688 | target_arch = "x86" , |
689 | target_arch = "x86_64" , |
690 | )))] |
691 | { |
692 | ret_usize(syscall!(__NR_recv, fd, buf, pass_usize(len), flags)) |
693 | } |
694 | #[cfg (any( |
695 | target_arch = "aarch64" , |
696 | target_arch = "mips64" , |
697 | target_arch = "mips64r6" , |
698 | target_arch = "riscv64" , |
699 | target_arch = "s390x" , |
700 | target_arch = "x86_64" , |
701 | ))] |
702 | { |
703 | ret_usize(syscall!( |
704 | __NR_recvfrom, |
705 | fd, |
706 | buf, |
707 | pass_usize(len), |
708 | flags, |
709 | zero(), |
710 | zero() |
711 | )) |
712 | } |
713 | #[cfg (target_arch = "x86" )] |
714 | { |
715 | ret_usize(syscall!( |
716 | __NR_socketcall, |
717 | x86_sys(SYS_RECV), |
718 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
719 | fd.into(), |
720 | buf.into(), |
721 | pass_usize(len), |
722 | flags.into(), |
723 | ]) |
724 | )) |
725 | } |
726 | } |
727 | |
728 | #[inline ] |
729 | pub(crate) unsafe fn recvfrom( |
730 | fd: BorrowedFd<'_>, |
731 | buf: *mut u8, |
732 | len: usize, |
733 | flags: RecvFlags, |
734 | ) -> io::Result<(usize, Option<SocketAddrAny>)> { |
735 | let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t; |
736 | let mut storage = MaybeUninit::<sockaddr>::uninit(); |
737 | |
738 | // `recvfrom` does not write to the storage if the socket is |
739 | // connection-oriented sockets, so we initialize the family field to |
740 | // `AF_UNSPEC` so that we can detect this case. |
741 | initialize_family_to_unspec(storage.as_mut_ptr()); |
742 | |
743 | #[cfg (not(target_arch = "x86" ))] |
744 | let nread = ret_usize(syscall!( |
745 | __NR_recvfrom, |
746 | fd, |
747 | buf, |
748 | pass_usize(len), |
749 | flags, |
750 | &mut storage, |
751 | by_mut(&mut addrlen) |
752 | ))?; |
753 | #[cfg (target_arch = "x86" )] |
754 | let nread = ret_usize(syscall!( |
755 | __NR_socketcall, |
756 | x86_sys(SYS_RECVFROM), |
757 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
758 | fd.into(), |
759 | buf.into(), |
760 | pass_usize(len), |
761 | flags.into(), |
762 | (&mut storage).into(), |
763 | by_mut(&mut addrlen), |
764 | ]) |
765 | ))?; |
766 | |
767 | Ok(( |
768 | nread, |
769 | maybe_read_sockaddr_os(&storage.assume_init(), addrlen.try_into().unwrap()), |
770 | )) |
771 | } |
772 | |
773 | #[inline ] |
774 | pub(crate) fn getpeername(fd: BorrowedFd<'_>) -> io::Result<Option<SocketAddrAny>> { |
775 | #[cfg (not(target_arch = "x86" ))] |
776 | unsafe { |
777 | let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t; |
778 | let mut storage = MaybeUninit::<sockaddr>::uninit(); |
779 | ret(syscall!( |
780 | __NR_getpeername, |
781 | fd, |
782 | &mut storage, |
783 | by_mut(&mut addrlen) |
784 | ))?; |
785 | Ok(maybe_read_sockaddr_os( |
786 | &storage.assume_init(), |
787 | addrlen.try_into().unwrap(), |
788 | )) |
789 | } |
790 | #[cfg (target_arch = "x86" )] |
791 | unsafe { |
792 | let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t; |
793 | let mut storage = MaybeUninit::<sockaddr>::uninit(); |
794 | ret(syscall!( |
795 | __NR_socketcall, |
796 | x86_sys(SYS_GETPEERNAME), |
797 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
798 | fd.into(), |
799 | (&mut storage).into(), |
800 | by_mut(&mut addrlen), |
801 | ]) |
802 | ))?; |
803 | Ok(maybe_read_sockaddr_os( |
804 | &storage.assume_init(), |
805 | addrlen.try_into().unwrap(), |
806 | )) |
807 | } |
808 | } |
809 | |
810 | #[inline ] |
811 | pub(crate) fn getsockname(fd: BorrowedFd<'_>) -> io::Result<SocketAddrAny> { |
812 | #[cfg (not(target_arch = "x86" ))] |
813 | unsafe { |
814 | let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t; |
815 | let mut storage = MaybeUninit::<sockaddr>::uninit(); |
816 | ret(syscall!( |
817 | __NR_getsockname, |
818 | fd, |
819 | &mut storage, |
820 | by_mut(&mut addrlen) |
821 | ))?; |
822 | Ok(read_sockaddr_os( |
823 | &storage.assume_init(), |
824 | addrlen.try_into().unwrap(), |
825 | )) |
826 | } |
827 | #[cfg (target_arch = "x86" )] |
828 | unsafe { |
829 | let mut addrlen = core::mem::size_of::<sockaddr>() as socklen_t; |
830 | let mut storage = MaybeUninit::<sockaddr>::uninit(); |
831 | ret(syscall!( |
832 | __NR_socketcall, |
833 | x86_sys(SYS_GETSOCKNAME), |
834 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
835 | fd.into(), |
836 | (&mut storage).into(), |
837 | by_mut(&mut addrlen), |
838 | ]) |
839 | ))?; |
840 | Ok(read_sockaddr_os( |
841 | &storage.assume_init(), |
842 | addrlen.try_into().unwrap(), |
843 | )) |
844 | } |
845 | } |
846 | |
847 | #[inline ] |
848 | pub(crate) fn bind_v4(fd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> { |
849 | #[cfg (not(target_arch = "x86" ))] |
850 | unsafe { |
851 | ret(raw:syscall_readonly!( |
852 | __NR_bind, |
853 | fd, |
854 | by_ref(&encode_sockaddr_v4(addr)), |
855 | size_of::<sockaddr_in, _>() |
856 | )) |
857 | } |
858 | #[cfg (target_arch = "x86" )] |
859 | unsafe { |
860 | ret(syscall_readonly!( |
861 | __NR_socketcall, |
862 | x86_sys(SYS_BIND), |
863 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
864 | fd.into(), |
865 | by_ref(&encode_sockaddr_v4(addr)), |
866 | size_of::<sockaddr_in, _>(), |
867 | ]) |
868 | )) |
869 | } |
870 | } |
871 | |
872 | #[inline ] |
873 | pub(crate) fn bind_v6(fd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> { |
874 | #[cfg (not(target_arch = "x86" ))] |
875 | unsafe { |
876 | ret(raw:syscall_readonly!( |
877 | __NR_bind, |
878 | fd, |
879 | by_ref(&encode_sockaddr_v6(addr)), |
880 | size_of::<sockaddr_in6, _>() |
881 | )) |
882 | } |
883 | #[cfg (target_arch = "x86" )] |
884 | unsafe { |
885 | ret(syscall_readonly!( |
886 | __NR_socketcall, |
887 | x86_sys(SYS_BIND), |
888 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
889 | fd.into(), |
890 | by_ref(&encode_sockaddr_v6(addr)), |
891 | size_of::<sockaddr_in6, _>(), |
892 | ]) |
893 | )) |
894 | } |
895 | } |
896 | |
897 | #[inline ] |
898 | pub(crate) fn bind_unix(fd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> { |
899 | #[cfg (not(target_arch = "x86" ))] |
900 | unsafe { |
901 | ret(raw:syscall_readonly!( |
902 | __NR_bind, |
903 | fd, |
904 | by_ref(&addr.unix), |
905 | socklen_t(addr.addr_len()) |
906 | )) |
907 | } |
908 | #[cfg (target_arch = "x86" )] |
909 | unsafe { |
910 | ret(syscall_readonly!( |
911 | __NR_socketcall, |
912 | x86_sys(SYS_BIND), |
913 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
914 | fd.into(), |
915 | by_ref(&addr.unix), |
916 | socklen_t(addr.addr_len()), |
917 | ]) |
918 | )) |
919 | } |
920 | } |
921 | |
922 | #[cfg (target_os = "linux" )] |
923 | #[inline ] |
924 | pub(crate) fn bind_xdp(fd: BorrowedFd<'_>, addr: &SocketAddrXdp) -> io::Result<()> { |
925 | #[cfg (not(target_arch = "x86" ))] |
926 | unsafe { |
927 | ret(raw:syscall_readonly!( |
928 | __NR_bind, |
929 | fd, |
930 | by_ref(&encode_sockaddr_xdp(addr)), |
931 | size_of::<c::sockaddr_xdp, _>() |
932 | )) |
933 | } |
934 | #[cfg (target_arch = "x86" )] |
935 | unsafe { |
936 | ret(syscall_readonly!( |
937 | __NR_socketcall, |
938 | x86_sys(SYS_BIND), |
939 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
940 | fd.into(), |
941 | by_ref(&encode_sockaddr_xdp(addr)), |
942 | size_of::<c::sockaddr_xdp, _>(), |
943 | ]) |
944 | )) |
945 | } |
946 | } |
947 | |
948 | #[inline ] |
949 | pub(crate) fn connect_v4(fd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> { |
950 | #[cfg (not(target_arch = "x86" ))] |
951 | unsafe { |
952 | ret(raw:syscall_readonly!( |
953 | __NR_connect, |
954 | fd, |
955 | by_ref(&encode_sockaddr_v4(addr)), |
956 | size_of::<sockaddr_in, _>() |
957 | )) |
958 | } |
959 | #[cfg (target_arch = "x86" )] |
960 | unsafe { |
961 | ret(syscall_readonly!( |
962 | __NR_socketcall, |
963 | x86_sys(SYS_CONNECT), |
964 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
965 | fd.into(), |
966 | by_ref(&encode_sockaddr_v4(addr)), |
967 | size_of::<sockaddr_in, _>(), |
968 | ]) |
969 | )) |
970 | } |
971 | } |
972 | |
973 | #[inline ] |
974 | pub(crate) fn connect_v6(fd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> { |
975 | #[cfg (not(target_arch = "x86" ))] |
976 | unsafe { |
977 | ret(raw:syscall_readonly!( |
978 | __NR_connect, |
979 | fd, |
980 | by_ref(&encode_sockaddr_v6(addr)), |
981 | size_of::<sockaddr_in6, _>() |
982 | )) |
983 | } |
984 | #[cfg (target_arch = "x86" )] |
985 | unsafe { |
986 | ret(syscall_readonly!( |
987 | __NR_socketcall, |
988 | x86_sys(SYS_CONNECT), |
989 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
990 | fd.into(), |
991 | by_ref(&encode_sockaddr_v6(addr)), |
992 | size_of::<sockaddr_in6, _>(), |
993 | ]) |
994 | )) |
995 | } |
996 | } |
997 | |
998 | #[inline ] |
999 | pub(crate) fn connect_unix(fd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> { |
1000 | #[cfg (not(target_arch = "x86" ))] |
1001 | unsafe { |
1002 | ret(raw:syscall_readonly!( |
1003 | __NR_connect, |
1004 | fd, |
1005 | by_ref(&addr.unix), |
1006 | socklen_t(addr.addr_len()) |
1007 | )) |
1008 | } |
1009 | #[cfg (target_arch = "x86" )] |
1010 | unsafe { |
1011 | ret(syscall_readonly!( |
1012 | __NR_socketcall, |
1013 | x86_sys(SYS_CONNECT), |
1014 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
1015 | fd.into(), |
1016 | by_ref(&addr.unix), |
1017 | socklen_t(addr.addr_len()), |
1018 | ]) |
1019 | )) |
1020 | } |
1021 | } |
1022 | |
1023 | #[inline ] |
1024 | pub(crate) fn connect_unspec(fd: BorrowedFd<'_>) -> io::Result<()> { |
1025 | debug_assert_eq!(c::AF_UNSPEC, 0); |
1026 | let addr = MaybeUninit::<c::sockaddr_storage>::zeroed(); |
1027 | |
1028 | #[cfg (not(target_arch = "x86" ))] |
1029 | unsafe { |
1030 | ret(syscall_readonly!( |
1031 | __NR_connect, |
1032 | fd, |
1033 | by_ref(&addr), |
1034 | size_of::<c::sockaddr_storage, _>() |
1035 | )) |
1036 | } |
1037 | #[cfg (target_arch = "x86" )] |
1038 | unsafe { |
1039 | ret(syscall_readonly!( |
1040 | __NR_socketcall, |
1041 | x86_sys(SYS_CONNECT), |
1042 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[ |
1043 | fd.into(), |
1044 | by_ref(&addr), |
1045 | size_of::<c::sockaddr_storage, _>(), |
1046 | ]) |
1047 | )) |
1048 | } |
1049 | } |
1050 | |
1051 | #[inline ] |
1052 | pub(crate) fn listen(fd: BorrowedFd<'_>, backlog: c::c_int) -> io::Result<()> { |
1053 | #[cfg (not(target_arch = "x86" ))] |
1054 | unsafe { |
1055 | ret(raw:syscall_readonly!(__NR_listen, fd, c_int(backlog))) |
1056 | } |
1057 | #[cfg (target_arch = "x86" )] |
1058 | unsafe { |
1059 | ret(syscall_readonly!( |
1060 | __NR_socketcall, |
1061 | x86_sys(SYS_LISTEN), |
1062 | slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), c_int(backlog)]) |
1063 | )) |
1064 | } |
1065 | } |
1066 | |