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(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]
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(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]
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(target_arch = "x86"))]
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}
153
154#[inline]
155pub(crate) fn accept_with(fd: BorrowedFd<'_>, flags: SocketFlags) -> io::Result<OwnedFd> {
156 #[cfg(not(target_arch = "x86"))]
157 unsafe {
158 let fd: OwnedFd = ret_owned_fd(raw: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]
173pub(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]
210pub(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]
252pub(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]
293pub(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: msghdr| {
300 #[cfg(not(target_arch = "x86"))]
301 let result: Result =
302 unsafe { ret_usize(raw: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]
322pub(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: msghdr| {
330 #[cfg(not(target_arch = "x86"))]
331 let result: Result =
332 unsafe { ret_usize(raw: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]
352pub(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: msghdr| {
360 #[cfg(not(target_arch = "x86"))]
361 let result: Result =
362 unsafe { ret_usize(raw: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]
382pub(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: msghdr| {
390 #[cfg(not(target_arch = "x86"))]
391 let result: Result =
392 unsafe { ret_usize(raw: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]
413pub(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: msghdr| {
421 #[cfg(not(target_arch = "x86"))]
422 let result: Result =
423 unsafe { ret_usize(raw: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]
443pub(crate) fn shutdown(fd: BorrowedFd<'_>, how: Shutdown) -> io::Result<()> {
444 #[cfg(not(target_arch = "x86"))]
445 unsafe {
446 ret(raw: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]
463pub(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]
511pub(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]
549pub(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]
587pub(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]
626pub(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]
664pub(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]
715pub(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]
760pub(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]
797pub(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]
834pub(crate) fn bind_v4(fd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> {
835 #[cfg(not(target_arch = "x86"))]
836 unsafe {
837 ret(raw: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]
859pub(crate) fn bind_v6(fd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> {
860 #[cfg(not(target_arch = "x86"))]
861 unsafe {
862 ret(raw: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]
884pub(crate) fn bind_unix(fd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> {
885 #[cfg(not(target_arch = "x86"))]
886 unsafe {
887 ret(raw: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]
910pub(crate) fn bind_xdp(fd: BorrowedFd<'_>, addr: &SocketAddrXdp) -> io::Result<()> {
911 #[cfg(not(target_arch = "x86"))]
912 unsafe {
913 ret(raw: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]
935pub(crate) fn connect_v4(fd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> {
936 #[cfg(not(target_arch = "x86"))]
937 unsafe {
938 ret(raw: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]
960pub(crate) fn connect_v6(fd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> {
961 #[cfg(not(target_arch = "x86"))]
962 unsafe {
963 ret(raw: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]
985pub(crate) fn connect_unix(fd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> {
986 #[cfg(not(target_arch = "x86"))]
987 unsafe {
988 ret(raw: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]
1010pub(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]
1038pub(crate) fn listen(fd: BorrowedFd<'_>, backlog: c::c_int) -> io::Result<()> {
1039 #[cfg(not(target_arch = "x86"))]
1040 unsafe {
1041 ret(raw: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