rustix/backend/linux_raw/net/
syscalls.rs

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")]
9use super::msghdr::with_xdp_msghdr;
10use super::msghdr::{
11    with_noaddr_msghdr, with_recv_msghdr, with_unix_msghdr, with_v4_msghdr, with_v6_msghdr,
12};
13use super::read_sockaddr::{initialize_family_to_unspec, maybe_read_sockaddr_os, read_sockaddr_os};
14use super::send_recv::{RecvFlags, SendFlags};
15#[cfg(target_os = "linux")]
16use super::write_sockaddr::encode_sockaddr_xdp;
17use super::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6};
18use crate::backend::c;
19use 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};
23use crate::fd::{BorrowedFd, OwnedFd};
24use crate::io::{self, IoSlice, IoSliceMut};
25#[cfg(target_os = "linux")]
26use crate::net::xdp::SocketAddrXdp;
27use crate::net::{
28    AddressFamily, Protocol, RecvAncillaryBuffer, RecvMsgReturn, SendAncillaryBuffer, Shutdown,
29    SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6, SocketFlags, SocketType,
30};
31use c::{sockaddr, sockaddr_in, sockaddr_in6, socklen_t};
32use core::mem::MaybeUninit;
33#[cfg(target_arch = "x86")]
34use {
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]
45pub(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]
69pub(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]
99pub(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]
137pub(crate) fn accept(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
138    #[cfg(not(any(target_arch = "x86", target_arch = "s390x")))]
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    #[cfg(target_arch = "s390x")]
153    {
154        // accept is not available on s390x
155        accept_with(fd, SocketFlags::empty())
156    }
157}
158
159#[inline]
160pub(crate) fn accept_with(fd: BorrowedFd<'_>, flags: SocketFlags) -> io::Result<OwnedFd> {
161    #[cfg(not(target_arch = "x86"))]
162    unsafe {
163        let fd = ret_owned_fd(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]
178pub(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]
220pub(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]
262pub(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]
303pub(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| {
310        #[cfg(not(target_arch = "x86"))]
311        let result =
312            unsafe { ret_usize(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]
332pub(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| {
340        #[cfg(not(target_arch = "x86"))]
341        let result =
342            unsafe { ret_usize(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]
362pub(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| {
370        #[cfg(not(target_arch = "x86"))]
371        let result =
372            unsafe { ret_usize(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]
392pub(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| {
400        #[cfg(not(target_arch = "x86"))]
401        let result =
402            unsafe { ret_usize(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]
423pub(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| {
431        #[cfg(not(target_arch = "x86"))]
432        let result =
433            unsafe { ret_usize(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]
453pub(crate) fn shutdown(fd: BorrowedFd<'_>, how: Shutdown) -> io::Result<()> {
454    #[cfg(not(target_arch = "x86"))]
455    unsafe {
456        ret(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]
473pub(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]
523pub(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]
561pub(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]
599pub(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]
638pub(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]
676pub(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]
729pub(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]
774pub(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]
811pub(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]
848pub(crate) fn bind_v4(fd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> {
849    #[cfg(not(target_arch = "x86"))]
850    unsafe {
851        ret(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]
873pub(crate) fn bind_v6(fd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> {
874    #[cfg(not(target_arch = "x86"))]
875    unsafe {
876        ret(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]
898pub(crate) fn bind_unix(fd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> {
899    #[cfg(not(target_arch = "x86"))]
900    unsafe {
901        ret(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]
924pub(crate) fn bind_xdp(fd: BorrowedFd<'_>, addr: &SocketAddrXdp) -> io::Result<()> {
925    #[cfg(not(target_arch = "x86"))]
926    unsafe {
927        ret(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]
949pub(crate) fn connect_v4(fd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> {
950    #[cfg(not(target_arch = "x86"))]
951    unsafe {
952        ret(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]
974pub(crate) fn connect_v6(fd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> {
975    #[cfg(not(target_arch = "x86"))]
976    unsafe {
977        ret(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]
999pub(crate) fn connect_unix(fd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> {
1000    #[cfg(not(target_arch = "x86"))]
1001    unsafe {
1002        ret(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]
1024pub(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]
1052pub(crate) fn listen(fd: BorrowedFd<'_>, backlog: c::c_int) -> io::Result<()> {
1053    #[cfg(not(target_arch = "x86"))]
1054    unsafe {
1055        ret(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}