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