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
8use super::msghdr::{noaddr_msghdr, with_msghdr, with_recv_msghdr};
9use super::read_sockaddr::initialize_family_to_unspec;
10use super::send_recv::{RecvFlags, ReturnFlags, SendFlags};
11use crate::backend::c;
12#[cfg(target_os = "linux")]
13use crate::backend::conv::slice_mut;
14use crate::backend::conv::{
15    by_mut, by_ref, c_int, c_uint, pass_usize, ret, ret_owned_fd, ret_usize, size_of, slice,
16    socklen_t, zero,
17};
18use crate::backend::reg::raw_arg;
19use crate::fd::{BorrowedFd, OwnedFd};
20use crate::io::{self, IoSlice, IoSliceMut};
21use crate::net::addr::SocketAddrArg;
22#[cfg(target_os = "linux")]
23use crate::net::MMsgHdr;
24use crate::net::{
25    AddressFamily, Protocol, RecvAncillaryBuffer, RecvMsg, SendAncillaryBuffer, Shutdown,
26    SocketAddrAny, SocketAddrBuf, SocketFlags, SocketType,
27};
28use core::mem::MaybeUninit;
29#[cfg(target_arch = "x86")]
30use {
31    crate::backend::conv::{slice_just_addr, x86_sys},
32    crate::backend::reg::{ArgReg, SocketArg},
33    linux_raw_sys::net::{
34        SYS_ACCEPT, SYS_ACCEPT4, SYS_BIND, SYS_CONNECT, SYS_GETPEERNAME, SYS_GETSOCKNAME,
35        SYS_LISTEN, SYS_RECV, SYS_RECVFROM, SYS_RECVMSG, SYS_SEND, SYS_SENDMMSG, SYS_SENDMSG,
36        SYS_SENDTO, SYS_SHUTDOWN, SYS_SOCKET, SYS_SOCKETPAIR,
37    },
38};
39
40#[inline]
41pub(crate) fn socket(
42    family: AddressFamily,
43    type_: SocketType,
44    protocol: Option<Protocol>,
45) -> io::Result<OwnedFd> {
46    #[cfg(not(target_arch = "x86"))]
47    unsafe {
48        ret_owned_fd(syscall_readonly!(__NR_socket, family, type_, protocol))
49    }
50    #[cfg(target_arch = "x86")]
51    unsafe {
52        ret_owned_fd(syscall_readonly!(
53            __NR_socketcall,
54            x86_sys(SYS_SOCKET),
55            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
56                family.into(),
57                type_.into(),
58                protocol.into(),
59            ])
60        ))
61    }
62}
63
64#[inline]
65pub(crate) fn socket_with(
66    family: AddressFamily,
67    type_: SocketType,
68    flags: SocketFlags,
69    protocol: Option<Protocol>,
70) -> io::Result<OwnedFd> {
71    #[cfg(not(target_arch = "x86"))]
72    unsafe {
73        ret_owned_fd(syscall_readonly!(
74            __NR_socket,
75            family,
76            (type_, flags),
77            protocol
78        ))
79    }
80    #[cfg(target_arch = "x86")]
81    unsafe {
82        ret_owned_fd(syscall_readonly!(
83            __NR_socketcall,
84            x86_sys(SYS_SOCKET),
85            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
86                family.into(),
87                (type_, flags).into(),
88                protocol.into(),
89            ])
90        ))
91    }
92}
93
94#[inline]
95pub(crate) fn socketpair(
96    family: AddressFamily,
97    type_: SocketType,
98    flags: SocketFlags,
99    protocol: Option<Protocol>,
100) -> io::Result<(OwnedFd, OwnedFd)> {
101    #[cfg(not(target_arch = "x86"))]
102    unsafe {
103        let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
104        ret(syscall!(
105            __NR_socketpair,
106            family,
107            (type_, flags),
108            protocol,
109            &mut result
110        ))?;
111        let [fd0, fd1] = result.assume_init();
112        Ok((fd0, fd1))
113    }
114    #[cfg(target_arch = "x86")]
115    unsafe {
116        let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
117        ret(syscall!(
118            __NR_socketcall,
119            x86_sys(SYS_SOCKETPAIR),
120            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
121                family.into(),
122                (type_, flags).into(),
123                protocol.into(),
124                (&mut result).into(),
125            ])
126        ))?;
127        let [fd0, fd1] = result.assume_init();
128        Ok((fd0, fd1))
129    }
130}
131
132#[inline]
133pub(crate) fn accept(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
134    #[cfg(not(any(target_arch = "x86", target_arch = "s390x")))]
135    unsafe {
136        let fd = ret_owned_fd(syscall_readonly!(__NR_accept, fd, zero(), zero()))?;
137        Ok(fd)
138    }
139    #[cfg(target_arch = "x86")]
140    unsafe {
141        let fd = ret_owned_fd(syscall_readonly!(
142            __NR_socketcall,
143            x86_sys(SYS_ACCEPT),
144            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), zero(), zero()])
145        ))?;
146        Ok(fd)
147    }
148    #[cfg(target_arch = "s390x")]
149    {
150        // accept is not available on s390x
151        accept_with(fd, SocketFlags::empty())
152    }
153}
154
155#[inline]
156pub(crate) fn accept_with(fd: BorrowedFd<'_>, flags: SocketFlags) -> io::Result<OwnedFd> {
157    #[cfg(not(target_arch = "x86"))]
158    unsafe {
159        let fd = ret_owned_fd(syscall_readonly!(__NR_accept4, fd, zero(), zero(), flags))?;
160        Ok(fd)
161    }
162    #[cfg(target_arch = "x86")]
163    unsafe {
164        let fd = ret_owned_fd(syscall_readonly!(
165            __NR_socketcall,
166            x86_sys(SYS_ACCEPT4),
167            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), zero(), zero(), flags.into()])
168        ))?;
169        Ok(fd)
170    }
171}
172
173#[inline]
174pub(crate) fn acceptfrom(fd: BorrowedFd<'_>) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
175    #[cfg(not(any(target_arch = "x86", target_arch = "s390x")))]
176    unsafe {
177        let mut addr = SocketAddrBuf::new();
178        let fd = ret_owned_fd(syscall!(
179            __NR_accept,
180            fd,
181            &mut addr.storage,
182            by_mut(&mut addr.len)
183        ))?;
184        Ok((fd, addr.into_any_option()))
185    }
186    #[cfg(target_arch = "x86")]
187    unsafe {
188        let mut addr = SocketAddrBuf::new();
189        let fd = ret_owned_fd(syscall!(
190            __NR_socketcall,
191            x86_sys(SYS_ACCEPT),
192            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
193                fd.into(),
194                (&mut addr.storage).into(),
195                by_mut(&mut addr.len),
196            ])
197        ))?;
198        Ok((fd, addr.into_any_option()))
199    }
200    #[cfg(target_arch = "s390x")]
201    {
202        // accept is not available on s390x
203        acceptfrom_with(fd, SocketFlags::empty())
204    }
205}
206
207#[inline]
208pub(crate) fn acceptfrom_with(
209    fd: BorrowedFd<'_>,
210    flags: SocketFlags,
211) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
212    #[cfg(not(target_arch = "x86"))]
213    unsafe {
214        let mut addr = SocketAddrBuf::new();
215        let fd = ret_owned_fd(syscall!(
216            __NR_accept4,
217            fd,
218            &mut addr.storage,
219            by_mut(&mut addr.len),
220            flags
221        ))?;
222        Ok((fd, addr.into_any_option()))
223    }
224    #[cfg(target_arch = "x86")]
225    unsafe {
226        let mut addr = SocketAddrBuf::new();
227        let fd = ret_owned_fd(syscall!(
228            __NR_socketcall,
229            x86_sys(SYS_ACCEPT4),
230            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
231                fd.into(),
232                (&mut addr.storage).into(),
233                by_mut(&mut addr.len),
234                flags.into(),
235            ])
236        ))?;
237        Ok((fd, addr.into_any_option()))
238    }
239}
240
241#[inline]
242pub(crate) fn recvmsg(
243    sockfd: BorrowedFd<'_>,
244    iov: &mut [IoSliceMut<'_>],
245    control: &mut RecvAncillaryBuffer<'_>,
246    msg_flags: RecvFlags,
247) -> io::Result<RecvMsg> {
248    let mut addr = SocketAddrBuf::new();
249
250    // SAFETY: This passes the `msghdr` reference to the OS which reads the
251    // buffers only within the designated bounds.
252    let (bytes, flags) = unsafe {
253        with_recv_msghdr(&mut addr, iov, control, |msghdr| {
254            #[cfg(not(target_arch = "x86"))]
255            let result = ret_usize(syscall!(__NR_recvmsg, sockfd, by_mut(msghdr), msg_flags));
256
257            #[cfg(target_arch = "x86")]
258            let result = ret_usize(syscall!(
259                __NR_socketcall,
260                x86_sys(SYS_RECVMSG),
261                slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
262                    sockfd.into(),
263                    by_mut(msghdr),
264                    msg_flags.into(),
265                ])
266            ));
267
268            result.map(|bytes| (bytes, msghdr.msg_flags))
269        })?
270    };
271
272    // Get the address of the sender, if any.
273    Ok(RecvMsg {
274        bytes,
275        address: unsafe { addr.into_any_option() },
276        flags: ReturnFlags::from_bits_retain(flags),
277    })
278}
279
280#[inline]
281pub(crate) fn sendmsg(
282    sockfd: BorrowedFd<'_>,
283    iov: &[IoSlice<'_>],
284    control: &mut SendAncillaryBuffer<'_, '_, '_>,
285    msg_flags: SendFlags,
286) -> io::Result<usize> {
287    let msghdr = noaddr_msghdr(iov, control);
288
289    #[cfg(not(target_arch = "x86"))]
290    let result = unsafe { ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) };
291
292    #[cfg(target_arch = "x86")]
293    let result = unsafe {
294        ret_usize(syscall!(
295            __NR_socketcall,
296            x86_sys(SYS_SENDMSG),
297            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
298                sockfd.into(),
299                by_ref(&msghdr),
300                msg_flags.into()
301            ])
302        ))
303    };
304
305    result
306}
307
308#[inline]
309pub(crate) fn sendmsg_addr(
310    sockfd: BorrowedFd<'_>,
311    addr: &impl SocketAddrArg,
312    iov: &[IoSlice<'_>],
313    control: &mut SendAncillaryBuffer<'_, '_, '_>,
314    msg_flags: SendFlags,
315) -> io::Result<usize> {
316    // SAFETY: This passes the `msghdr` reference to the OS which reads the
317    // buffers only within the designated bounds.
318    unsafe {
319        with_msghdr(addr, iov, control, |msghdr| {
320            #[cfg(not(target_arch = "x86"))]
321            let result = ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(msghdr), msg_flags));
322
323            #[cfg(target_arch = "x86")]
324            let result = ret_usize(syscall!(
325                __NR_socketcall,
326                x86_sys(SYS_SENDMSG),
327                slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
328                    sockfd.into(),
329                    by_ref(msghdr),
330                    msg_flags.into(),
331                ])
332            ));
333
334            result
335        })
336    }
337}
338
339#[cfg(target_os = "linux")]
340#[inline]
341pub(crate) fn sendmmsg(
342    sockfd: BorrowedFd<'_>,
343    msgs: &mut [MMsgHdr<'_>],
344    flags: SendFlags,
345) -> io::Result<usize> {
346    let (msgs, len) = slice_mut(msgs);
347
348    #[cfg(not(target_arch = "x86"))]
349    let result = unsafe { ret_usize(syscall!(__NR_sendmmsg, sockfd, msgs, len, flags)) };
350
351    #[cfg(target_arch = "x86")]
352    let result = unsafe {
353        ret_usize(syscall!(
354            __NR_socketcall,
355            x86_sys(SYS_SENDMMSG),
356            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[sockfd.into(), msgs, len, flags.into()])
357        ))
358    };
359
360    result
361}
362
363#[inline]
364pub(crate) fn shutdown(fd: BorrowedFd<'_>, how: Shutdown) -> io::Result<()> {
365    #[cfg(not(target_arch = "x86"))]
366    unsafe {
367        ret(syscall_readonly!(
368            __NR_shutdown,
369            fd,
370            c_uint(how as c::c_uint)
371        ))
372    }
373    #[cfg(target_arch = "x86")]
374    unsafe {
375        ret(syscall_readonly!(
376            __NR_socketcall,
377            x86_sys(SYS_SHUTDOWN),
378            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), c_uint(how as c::c_uint)])
379        ))
380    }
381}
382
383#[inline]
384pub(crate) fn send(fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags) -> io::Result<usize> {
385    let (buf_addr, buf_len) = slice(buf);
386
387    #[cfg(not(any(
388        target_arch = "aarch64",
389        target_arch = "mips64",
390        target_arch = "mips64r6",
391        target_arch = "riscv64",
392        target_arch = "s390x",
393        target_arch = "x86",
394        target_arch = "x86_64",
395    )))]
396    unsafe {
397        ret_usize(syscall_readonly!(__NR_send, fd, buf_addr, buf_len, flags))
398    }
399    #[cfg(any(
400        target_arch = "aarch64",
401        target_arch = "mips64",
402        target_arch = "mips64r6",
403        target_arch = "riscv64",
404        target_arch = "s390x",
405        target_arch = "x86_64",
406    ))]
407    unsafe {
408        ret_usize(syscall_readonly!(
409            __NR_sendto,
410            fd,
411            buf_addr,
412            buf_len,
413            flags,
414            zero(),
415            zero()
416        ))
417    }
418    #[cfg(target_arch = "x86")]
419    unsafe {
420        ret_usize(syscall_readonly!(
421            __NR_socketcall,
422            x86_sys(SYS_SEND),
423            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
424                fd.into(),
425                buf_addr,
426                buf_len,
427                flags.into()
428            ])
429        ))
430    }
431}
432
433#[inline]
434pub(crate) fn sendto(
435    fd: BorrowedFd<'_>,
436    buf: &[u8],
437    flags: SendFlags,
438    addr: &impl SocketAddrArg,
439) -> io::Result<usize> {
440    let (buf_addr, buf_len) = slice(buf);
441
442    // SAFETY: This passes the `addr_ptr` reference to the OS which reads the
443    // buffers only within the `addr_len` bound.
444    unsafe {
445        addr.with_sockaddr(|addr_ptr, addr_len| {
446            #[cfg(not(target_arch = "x86"))]
447            {
448                ret_usize(syscall_readonly!(
449                    __NR_sendto,
450                    fd,
451                    buf_addr,
452                    buf_len,
453                    flags,
454                    raw_arg(addr_ptr as *mut _),
455                    socklen_t(addr_len)
456                ))
457            }
458            #[cfg(target_arch = "x86")]
459            {
460                ret_usize(syscall_readonly!(
461                    __NR_socketcall,
462                    x86_sys(SYS_SENDTO),
463                    slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
464                        fd.into(),
465                        buf_addr,
466                        buf_len,
467                        flags.into(),
468                        raw_arg(addr_ptr as *mut _),
469                        socklen_t(addr_len)
470                    ])
471                ))
472            }
473        })
474    }
475}
476
477#[inline]
478pub(crate) unsafe fn recv(
479    fd: BorrowedFd<'_>,
480    buf: (*mut u8, usize),
481    flags: RecvFlags,
482) -> io::Result<usize> {
483    #[cfg(not(any(
484        target_arch = "aarch64",
485        target_arch = "mips64",
486        target_arch = "mips64r6",
487        target_arch = "riscv64",
488        target_arch = "s390x",
489        target_arch = "x86",
490        target_arch = "x86_64",
491    )))]
492    {
493        ret_usize(syscall!(__NR_recv, fd, buf.0, pass_usize(buf.1), flags))
494    }
495    #[cfg(any(
496        target_arch = "aarch64",
497        target_arch = "mips64",
498        target_arch = "mips64r6",
499        target_arch = "riscv64",
500        target_arch = "s390x",
501        target_arch = "x86_64",
502    ))]
503    {
504        ret_usize(syscall!(
505            __NR_recvfrom,
506            fd,
507            buf.0,
508            pass_usize(buf.1),
509            flags,
510            zero(),
511            zero()
512        ))
513    }
514    #[cfg(target_arch = "x86")]
515    {
516        ret_usize(syscall!(
517            __NR_socketcall,
518            x86_sys(SYS_RECV),
519            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
520                fd.into(),
521                buf.0.into(),
522                pass_usize(buf.1),
523                flags.into(),
524            ])
525        ))
526    }
527}
528
529#[inline]
530pub(crate) unsafe fn recvfrom(
531    fd: BorrowedFd<'_>,
532    buf: (*mut u8, usize),
533    flags: RecvFlags,
534) -> io::Result<(usize, Option<SocketAddrAny>)> {
535    let mut addr = SocketAddrBuf::new();
536
537    // `recvfrom` does not write to the storage if the socket is
538    // connection-oriented sockets, so we initialize the family field to
539    // `AF_UNSPEC` so that we can detect this case.
540    initialize_family_to_unspec(addr.storage.as_mut_ptr().cast::<c::sockaddr>());
541
542    #[cfg(not(target_arch = "x86"))]
543    let nread = ret_usize(syscall!(
544        __NR_recvfrom,
545        fd,
546        buf.0,
547        pass_usize(buf.1),
548        flags,
549        &mut addr.storage,
550        by_mut(&mut addr.len)
551    ))?;
552    #[cfg(target_arch = "x86")]
553    let nread = ret_usize(syscall!(
554        __NR_socketcall,
555        x86_sys(SYS_RECVFROM),
556        slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
557            fd.into(),
558            buf.0.into(),
559            pass_usize(buf.1),
560            flags.into(),
561            (&mut addr.storage).into(),
562            by_mut(&mut addr.len),
563        ])
564    ))?;
565
566    Ok((nread, addr.into_any_option()))
567}
568
569#[inline]
570pub(crate) fn getpeername(fd: BorrowedFd<'_>) -> io::Result<Option<SocketAddrAny>> {
571    #[cfg(not(target_arch = "x86"))]
572    unsafe {
573        let mut addr = SocketAddrBuf::new();
574        ret(syscall!(
575            __NR_getpeername,
576            fd,
577            &mut addr.storage,
578            by_mut(&mut addr.len)
579        ))?;
580        Ok(addr.into_any_option())
581    }
582    #[cfg(target_arch = "x86")]
583    unsafe {
584        let mut addr = SocketAddrBuf::new();
585        ret(syscall!(
586            __NR_socketcall,
587            x86_sys(SYS_GETPEERNAME),
588            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
589                fd.into(),
590                (&mut addr.storage).into(),
591                by_mut(&mut addr.len),
592            ])
593        ))?;
594        Ok(addr.into_any_option())
595    }
596}
597
598#[inline]
599pub(crate) fn getsockname(fd: BorrowedFd<'_>) -> io::Result<SocketAddrAny> {
600    #[cfg(not(target_arch = "x86"))]
601    unsafe {
602        let mut addr = SocketAddrBuf::new();
603        ret(syscall!(
604            __NR_getsockname,
605            fd,
606            &mut addr.storage,
607            by_mut(&mut addr.len)
608        ))?;
609        Ok(addr.into_any())
610    }
611    #[cfg(target_arch = "x86")]
612    unsafe {
613        let mut addr = SocketAddrBuf::new();
614        ret(syscall!(
615            __NR_socketcall,
616            x86_sys(SYS_GETSOCKNAME),
617            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
618                fd.into(),
619                (&mut addr.storage).into(),
620                by_mut(&mut addr.len),
621            ])
622        ))?;
623        Ok(addr.into_any())
624    }
625}
626
627#[inline]
628pub(crate) fn bind(fd: BorrowedFd<'_>, addr: &impl SocketAddrArg) -> io::Result<()> {
629    // SAFETY: This passes the `addr_ptr` reference to the OS which reads the
630    // buffers only within the `addr_len` bound.
631    unsafe {
632        addr.with_sockaddr(|addr_ptr, addr_len| {
633            #[cfg(not(target_arch = "x86"))]
634            {
635                ret(syscall_readonly!(
636                    __NR_bind,
637                    fd,
638                    raw_arg(addr_ptr as *mut _),
639                    socklen_t(addr_len)
640                ))
641            }
642            #[cfg(target_arch = "x86")]
643            {
644                ret(syscall_readonly!(
645                    __NR_socketcall,
646                    x86_sys(SYS_BIND),
647                    slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
648                        fd.into(),
649                        raw_arg(addr_ptr as *mut _),
650                        socklen_t(addr_len)
651                    ])
652                ))
653            }
654        })
655    }
656}
657
658#[inline]
659pub(crate) fn connect(fd: BorrowedFd<'_>, addr: &impl SocketAddrArg) -> io::Result<()> {
660    // SAFETY: This passes the `addr_ptr` reference to the OS which reads the
661    // buffers only within the `addr_len` bound.
662    unsafe {
663        addr.with_sockaddr(|addr_ptr, addr_len| {
664            #[cfg(not(target_arch = "x86"))]
665            {
666                ret(syscall_readonly!(
667                    __NR_connect,
668                    fd,
669                    raw_arg(addr_ptr as *mut _),
670                    socklen_t(addr_len)
671                ))
672            }
673            #[cfg(target_arch = "x86")]
674            {
675                ret(syscall_readonly!(
676                    __NR_socketcall,
677                    x86_sys(SYS_CONNECT),
678                    slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
679                        fd.into(),
680                        raw_arg(addr_ptr as *mut _),
681                        socklen_t(addr_len)
682                    ])
683                ))
684            }
685        })
686    }
687}
688
689#[inline]
690pub(crate) fn connect_unspec(fd: BorrowedFd<'_>) -> io::Result<()> {
691    debug_assert_eq!(c::AF_UNSPEC, 0);
692    let addr = MaybeUninit::<c::sockaddr_storage>::zeroed();
693
694    #[cfg(not(target_arch = "x86"))]
695    unsafe {
696        ret(syscall_readonly!(
697            __NR_connect,
698            fd,
699            by_ref(&addr),
700            size_of::<c::sockaddr_storage, _>()
701        ))
702    }
703    #[cfg(target_arch = "x86")]
704    unsafe {
705        ret(syscall_readonly!(
706            __NR_socketcall,
707            x86_sys(SYS_CONNECT),
708            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[
709                fd.into(),
710                by_ref(&addr),
711                size_of::<c::sockaddr_storage, _>(),
712            ])
713        ))
714    }
715}
716
717#[inline]
718pub(crate) fn listen(fd: BorrowedFd<'_>, backlog: c::c_int) -> io::Result<()> {
719    #[cfg(not(target_arch = "x86"))]
720    unsafe {
721        ret(syscall_readonly!(__NR_listen, fd, c_int(backlog)))
722    }
723    #[cfg(target_arch = "x86")]
724    unsafe {
725        ret(syscall_readonly!(
726            __NR_socketcall,
727            x86_sys(SYS_LISTEN),
728            slice_just_addr::<ArgReg<'_, SocketArg>, _>(&[fd.into(), c_int(backlog)])
729        ))
730    }
731}